Entity Framework.doc_第1页
Entity Framework.doc_第2页
Entity Framework.doc_第3页
Entity Framework.doc_第4页
Entity Framework.doc_第5页
已阅读5页,还剩41页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Entity Data Model (EDM) 深入分析, Part 1Entity Data Model是.NET Framework v3.5 SP1引入的新功能,比Linq To SQL更加强大的ORM,让开发人员只需要着眼于领域对象模型的开发,而不需要考虑它们是如何与关系数据库交互。本系列文章逐步深入介绍如下内容:EDMX Schema 文件、Model Browser、映射关系、产生的实体类(Generated entity classes)、文档(Documentation)等等。1. EDMX Schema 文件可以将EDMX作为XML文件打开,你会发现该文件包含3个主要部分。Conceptual Models (CSDL)Storage Models (SSDL)Mapping (MSL)一般情况下,你没有必要手动修改EDMX -XML文件。可视化的EDM 设计器、Mapping Details窗口和Model Browser 窗口包含有上述3个部分,并非常友好地显示整个Entity Data Model模型。当你编译项目时,MSBuild 将从EDMX文件提取CSDL/SSDL/MSL内容,并放置3个独立的XML文件到项目的输出目录。2. Model Browser 窗口Model Browser窗口以可视的树形图显示概念模型和存储模型。3. Mapping details 窗口EDM设计器也提供了一个不错的Mapping Details 窗口,包含2个视图。Map Entity to Tables / View这一视图显示了数据库中所有字段和相应实体中的属性,可以用来查看和编辑EDM的映射关系。Map Entity to Functions这一视图用来选择一个特定的存储过程来插入、更新或删除Entity实例。4. 生成的实体类(Generated Entity Classes)除了上述的XML Schema文件外,EDM向导也生成了实体类。下一步仔细分析.Designer.cs文件中的实体类,并和LINQ to SQL中的类进行比较。1) 比较 LINQ to SQL class 和 EDM EntityObject class/ LINQ to SQLTable(Name=dbo.Employees)public partial class Employee : INotifyPropertyChanging, INotifyPropertyChangedEDM类则是以不同的attributes,并且总是继承EntityObject或ComplexObject 类。EntityObject 类提供了变更跟踪和关系管理。/ Entity Data Modelglobal:System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName=NorthwindModel, Name=Employee)global:System.Runtime.Serialization.DataContractAttribute()global:System.Serializable()public partial class Employee : global:System.Data.Objects.DataClasses.EntityObject2) 比较LINQ to SQL entity constructor 和 EDM Create method/ LINQ to SQLpublic Employee()this._Employees = new EntitySet(new Action(this.attach_Employees), new Action(this.detach_Employees);this._EmployeeTerritories = new EntitySet(new Action(this.attach_EmployeeTerritories),new Action(this.detach_EmployeeTerritories);this._Orders = new EntitySet(new Action(this.attach_Orders), new Action(this.detach_Orders);this._Employee1 = default(EntityRef);OnCreated();EDM没有生成上述LINQ to SQL的构造函数,而是创建了一个特定的Create方法,并提供了所有必需属性(not nullable)的输入参数。/ Entity Data Modelpublic static Employee CreateEmployee(int employeeID, string lastName, string firstName)Employee employee = new Employee();employee.EmployeeID = employeeID;employee.LastName = lastName;employee.FirstName = firstName;return employee;3) 比较LINQ to SQL 和 EDM : 实体属性(entity property)/ LINQ to SQLColumn(Storage=_EmployeeID, AutoSync=AutoSync.OnInsert, DbType=Int NOT NULL IDENTITY, IsPrimaryKey=true, IsDbGenerated=true)public int EmployeeIDgetreturn this._EmployeeID;setif (this._EmployeeID != value)this.OnEmployeeIDChanging(value);this.SendPropertyChanging();this._EmployeeID = value;this.SendPropertyChanged(EmployeeID);this.OnEmployeeIDChanged();尽管EDM公有属性(public property)的attribute是不同的,但get和set 基本是一样的。/ Entity Data Modelglobal:System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)global:System.Runtime.Serialization.DataMemberAttribute()public int EmployeeIDgetreturn this._EmployeeID;setthis.OnEmployeeIDChanging(value);this.ReportPropertyChanging(EmployeeID);this._EmployeeID = global:System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value);this.ReportPropertyChanged(EmployeeID);this.OnEmployeeIDChanged();4) 比较LINQ to SQL Table 和 EDM ObjectQuery/ LINQ to SQLpublic System.Data.Linq.Table Employeesgetreturn this.GetTable();在LINQ to SQL中,调用GetTable 方法,返回实体集合。在EDM中,通过Object Services compoment 执行Entity SQL 查询,返回EntityType的计划EntitySet。/ Entity Data Modelglobal:System.ComponentModel.BrowsableAttribute(false)public global:System.Data.Objects.ObjectQuery Employeesgetif (this._Employees = null)this._Employees = base.CreateQuery(Employees);return this._Employees;private global:System.Data.Objects.ObjectQuery _Employees;5) 比较LINQ to SQL DataContext 和 EDM ObjectContext/ LINQ to SQLSystem.Data.Linq.Mapping.DatabaseAttribute(Name=Northwind)public partial class NorthwindDataContext : System.Data.Linq.DataContextEDM有一个类似于LINQ to SQL DataContext 的ObjectContext类,ObjectContext 类是负责与EDM 中实体类型交互的基本类。ObjectContext用来创建数据库连接、检索数据、持久化对象、以及对数据库的插入、更新和删除操作。/ Entity Data Modelpublic partial class NorthwindEntities : global:System.Data.Objects.ObjectContextObjectContext的连接字符串指向元数据(CSDL/SSDL/MSL 文件)和数据源(数据库连接字符串)。connectionString=metadata=.NorthwindModel.csdl|.NorthwindModel.ssdl|.NorthwindModel.msl;provider=System.Data.SqlClient;provider connection string="Data Source=SQLEXPRESS; Initial Catalog=Northwind; Integrated Security=True; MultipleActiveResultSets=True"5. Documentation 属性EDM中的实体类型(EntityTypes)、关联和属性有一个Documentation属性,对LINQ to SQL而言,这是一个新的属性。Documentation属性将更新生成的partial实体类的XML注释,可以用来生成代码文档的帮助文件。/ / Employee entity which corresponds with the Northwind.Employees table/ / / EmployeeID/ global:System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName=NorthwindModel, Name=Employee)global:System.Runtime.Serialization.DataContractAttribute()global:System.Serializable()public partial class Employee : global:System.Data.Objects.DataClasses.EntityObject英文链接:1. ADO.NET Entity Framework & LINQ to Entities,http:/www.scip.be/index.php?Page=ArticlesNET12Entity Data Model (EDM) 深入分析, Part 2实体 SQL (Entity SQL),它是一种新的 SQL 语言,其中加入了之前的 SQL 语言并不支持的基于概念的查询功能。ESQL 扩展现有 SQL 语言的方式与 EDM 扩展数据库中所使用的关系模型的方式十分类似。此外,ESQL 未绑定到任何特定于后台数据库的语法,因此可一次性编写查询(和/或应用程序),无论针对的是哪个后台数据库都无影响。Entity SQL 是基于文本的、面向集合的、延后绑定的查询语言,也受到了T-SQL的影响。可以使用Entity SQL 创建对EDM的查询,Entity SQL 既可以通过Object Services components来执行,也可以通过Entity Client components 来执行。Entity SQL 设计的非常灵活,因此也变得有些复杂。本篇文章侧重于不同的查询技术,仅仅使用简单的查询,不包含复杂的条件、关联和聚合公式。本系列文章上一篇:Entity Data Model (EDM) 深入分析, Part 11. 使用ObjectQuery 查询返回实体类型(Entity Type)集合下面演示如何执行Entity SQL 查询,返回实体类型的实例集合。1) 首先创建Northwind ObjectContext 实例。2) Entity SQL语句本身是字符串表达式,在大多数情况下,由SELECT-FROM 查询语句组成。在SELECT语句中使用VALUE关键字来表示返回的实体是一条数据行。3) 使用Object Services components 执行查询。调用ObjectContext 的工厂方法CreateQuery(),创建一个ObjectQuery 对象,该对象表示对存储数据源的查询,查询表达式为Entity SQL 语句。4) Entity Framework实体框架采用延迟装载(Deferred loading)。因此只有在显式需要数据时,才真正执行SQL语句。在这种情况下,在ForEach第一次迭代时,才执行查询语句。NorthwindEntities context = new NorthwindEntities();var sql = SELECT VALUE emp FROM NorthwindEntities.Employees AS emp;var query = context.CreateQuery(sql);foreach (var emp in query)Console.WriteLine(0 1 2 3, emp.EmployeeID, emp.FirstName, emp.LastName, emp.Country);除了使用工厂方法CreateQuery外,也可以直接创建ObjectQuery对象实例,并传入Object Context 参数,示例代码如下:NorthwindEntities context = new NorthwindEntities();var sql = NorthwindEntities.Employees;ObjectQuery query = new ObjectQuery(sql, context);foreach (var emp in query)Console.WriteLine(0 1 2 3, emp.EmployeeID, emp.FirstName, emp.LastName, emp.Country);下面增加一个WHERE条件:var sql = SELECT VALUE emp FROM NorthwindEntities.Employees AS emp + WHERE emp.Country = USA;var query = context.CreateQuery(sql);2. 带参数的ObjectQuery查询参数变量是在Entity SQL外定义的,在查询语句中需要以符合作为前缀定义变量名。参数定义为ObjectParameter 对象,然后增加到ObjectQuery 实例中。下面增加一个Country 变量:var sql = SELECT VALUE emp FROM NorthwindEntities.Employees AS emp + WHERE emp.Country = country;var query = context.CreateQuery(sql);query.Parameters.Add(new ObjectParameter(country, USA);同样以ObjectQuery 示例对象实现这一功能:var sql = SELECT VALUE emp FROM NorthwindEntities.Employees AS emp + WHERE emp.Country = country;ObjectQuery query = new ObjectQuery(sql, context);query.Parameters.Add(new ObjectParameter(country, USA);ObjectParameter对象也可以直接传入CreateQuery方法:var sql = SELECT VALUE emp FROM NorthwindEntities.Employees AS emp + WHERE emp.Country = country;var query = context.CreateQuery(sql, new ObjectParameter(country, USA);第三种方法的是使用Where 扩展方法,使用关键字it 指向当前的查询语句:var sql = SELECT VALUE emp FROM NorthwindEntities.Employees AS emp;var query = context.CreateQuery(sql).Where(it.Country = country, new ObjectParameter(country, USA);3. ObjectQuery 查询返回基本类型(Primitive Type)除了返回实体类型外,也可以返回基本类型集合,因此需要确保SELECT语句仅仅返回1个值,同时也需要在CreateQuery方法中指定需要返回的基本类型。var sql = SELECT VALUE emp.EmployeeID FROM NorthwindEntities.Employees AS emp + WHERE emp.Country = country;var query = context.CreateQuery(sql, new ObjectParameter(Country, USA);foreach (var id in query)Console.WriteLine(0, id.ToString();另一示例脚本:var sql = SELECT VALUE emp.Country FROM NorthwindEntities.Employees AS emp + WHERE emp.EmployeeID = id;var query = context.CreateQuery(sql, new ObjectParameter(id, 1);Console.WriteLine(query.First();除了使用 Entity SQL外,你也能使用查询构造(Query Builder)方法实现相同的效果。Entity SQL 提供了SelectValue 方法,可以提过隐式的行构造器,仅仅返回指定的列。string country = context.Employees.SelectValue(it.Country, new ObjectParameter(id, 1).First();Console.WriteLine(country);4. ObjectQuery 查询返回匿名类型也有可能需要调整数据,并使用ObjectQuery查询返回匿名类型。在CreateQuery 方法中,改变SELECT语句并使用DbDataRecord 类,DbDataReader类在.NET 1.0引入,它提供了对任何枚举类型的数据绑定支持。var sql = SELECT emp.LastName, emp.FirstName + FROM NorthwindEntities.Employees AS emp ;var query = context.CreateQuery(sql);foreach (var emp in query)Console.WriteLine(0 1, emp0, emp1);另一示例代码:var sql = SELECT emp.LastName AS FamilyName, emp.FirstName + FROM NorthwindEntities.Employees AS emp ;var query = context.CreateQuery(sql);foreach (var emp in query)Console.WriteLine(0 1, empFamilyName, empFirstName);Entity Data Model (EDM) 深入分析, Part 3EntityClient实体框架(Entity Framework)在ADO.NET 3.5 提供程序的基础上引入新的 ADO.NET 提供程序 EntityClient。EntityClient 看上去与之前使用的 ADO.NET 提供程序非常类似,它将提供第一个抽象,可允许开发人员使用标准的 Connection、Command 和 DataReader 对象依照 EDM 执行查询。它还会将映射域模型所需的客户端视图引擎(根据 EDM 定义的)添加到底层关系数据库架构。必要时,EntityClient 可借助 ESQL 查询字符串让开发人员以行和列的形式处理实体,而不必生成类来表示概念架构。1. EntityCommand 查询返回实体类型Entity SQL也可以通过EntityClient 来执行,尽管代码比较啰嗦,但是在某些情况下,也是优点。1) 首先创建EntityConnection,重用Northwind data context 的连接字符串,并打开连接。2) 创建 EntityCommand 对象,并传入Entity SQL语句和数据库连接对象。3) 创建DbDataReader对象,并循环读取返回的结果集。NorthwindEntities context = new NorthwindEntities();EntityConnection conn = new EntityConnection(context.Connection.ConnectionString);conn.Open();var sql = SELECT VALUE emp FROM NorthwindEntities.Employees AS emp;EntityCommand cmd = new EntityCommand(sql, conn);DbDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess);while (reader.Read()Console.WriteLine(0 1 2 3, readerEmployeeID, readerLastName, readerFirstName, readerCountry);当时使用SequentialAccess的DbDataReader时,需要小心访问数据,务必有序的读取。如你改变成员的顺序,将抛出InvalidOperationException 异常 - Attempt to read from column ordinal 0 is not valid. With CommandBehavior.SequentialAccess, you may only read from column ordinal 2 or greater.Console.WriteLine(0 1 2 3, readerLastName, readerEmployeeID,readerFirstName, readerCountry);2. EntityCommand 查询返回匿名类型采用相同的技术可以实现返回匿名类型。EntityConnection conn = new EntityConnection(context.Connection.ConnectionString);conn.Open();var sql = SELECT emp.LastName, emp.FirstName + FROM NorthwindEntities.Employees AS emp;EntityCommand cmd = new EntityCommand(sql, conn);DbDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess);while (reader.Read()Console.WriteLine(0 1, readerLastName, readerFirstName);3. EntityCommand 带参数查询EntityCommand 带参数也比较容易,在Entity SQL字符串中参数名称以作为前缀,接着创建EntityParameter对象,并增加到EntityCommand 的Parameters集合内。EntityConnection conn = new EntityConnection(context.Connection.ConnectionString);conn.Open();var sql = SELECT VALUE emp FROM NorthwindEntities.Employees AS emp + WHERE emp.Country = country;EntityCommand cmd = new EntityCommand(sql, conn);EntityParameter param = new EntityParameter(country, DbType.String);param.Value = USA;cmd.Parameters.Add(param);DbDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess);while (reader.Read()Console.WriteLine(0 1 2 3, readerEmployeeID, readerLastName, readerFirstName, readerCountry);LINQ to EntitiesLINQ是在.NET v3.5 引入的新技术。相对于前面的Entity SQL而言,我更偏爱LINQ to entities。LINQ查询虽然有一些局限,但是LINQ更容易、更自然,此外,还支持强类型,因此智能提示能帮助编写LINQ查询脚本。LINQ to Entities 与LINQ to Objects和LINQ to SQL 基本一样,因此下面简单演示2个基本的LINQ to Entities的查询。1. LINQ 带参数查询NorthwindEntities context = new NorthwindEntities();string country = USA;var query = from e in context.Employees where e.Country = country select e;foreach (var emp in query)Console.WriteLine(0 1 2 3, emp.EmployeeID, emp.FirstName, emp.LastName, emp.Country);2. LINQ 查询返回匿名类型NorthwindEntities context = new NorthwindEntities();var query = from e in context.Employees select new e.LastName, e.FirstName ;foreach (var emp in query)Console.WriteLine(0 1, emp.LastName, emp.FirstName);这篇文章对Entity Data Model 和Entity Framework 提供了各种查询技术进行了简单的介绍,希望对你有帮助。下一篇文章将介绍更高级的 Entity SQL 查询技术、查看SQL 语句、eager loading、变更跟踪、并发 等等。ADO.NET Entity Framework 深入分析, Part 4Entity Data Model 是一个概念模型,所有Entity SQL和LINQ to Entities 查询将最终转化为T-SQL的脚本,从数据库中查询数据。这里演示了几种方法来查看生成的T-SQL,有助于Debug或分析问题。1. 使用SQL Server Profiler 工具与LINQ to SQL比较而言,ObjectContext 类没有提供Log属性或者通用的log机制,因此,无法在Visual Studio 中跟踪所有的T-SQL语句。如果你想查看所有执行的T-SQL语句,你需要使用SQL Server的Profiler 工具,关于具体如何使用SQL Server Profiler工具,请参考如下文章:SQL Profiler: Features, functions and setup in SQL Server 2005/EntLib/archive/2008/10/27/sql-profiler-features-functions-and-setup-in-sql-server-2005.aspx2. ToTraceString 方法另外一种方法去查看生成的T-SQL语句的方法,包括 EntityCommand和ObjectQuery类都有一个ToTraceString() 方法。在一些情况下,可以用来查看内部到底生成什么SQL脚本,而不必一定要使用SQL Server Profiler 工具。需要注意的是:ToTraceString() 方法实际上没有执行查询操作,仅仅是转化查询为SQL脚本。通过增加一个断点,你可以轻松查看SQL脚本,需要记住的是:事先需要打开数据库连接,否则会抛出InvalidOperationException 异常(Execution of the command requires an open and available connection. The connections current state is closed.)(1)Entity SQL : EntityCommand.ToTraceString() 示例脚本 public IList GetParentCategory() IList result = null; EntityDataReader rdr; EntityCommand cmd; string esqlQuery; using (EntityConnection conn = new EntityConnection(name=AdventureWorksLTEntities) conn.Open(); esqlQuery = Select VALUE c from AdventureWorksLTEntities.Category AS c Where c.ParentCategory is null ; result = new List(); cmd = conn.CreateCommand(); cmd.CommandText = esqlQuery; Console.WriteLine(cmd.CommandText); Console.WriteLine(cmd.ToTraceString(); rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess); while (rdr.Read() result.Add(ductGateway.MaterializeCategory(rdr); conn.Close(); return result; 示例界面如下:图片看不清楚?请点击这里查看原图(大图)。(2)Entity SQL : ObjectQuery.ToTraceString() 示例脚本如下:NorthwindEntities context = new NorthwindEntities();var sql = SELECT VALUE emp FROM NorthwindEntities.Employees AS emp + WHERE emp.Country = country;var query = context.CreateQuery(sql);query.Parameters.Add(new ObjectParameter(country, USA);if (context.Connection.State != ConnectionState.Open)context.Connection.Open();Console.WriteLine(query.ToTraceString();(3)LINQ to Entities : (query as ObjectQuery).ToTraceString() 示例脚本需要使用类型转换,将LINQ to Entities (IQueryable) 查询转化为ObjectQuery,这样就可以调用ToTraceString() 方法了。NorthwindEntities context = new NorthwindEntities();string country = USA;var query = from e in context.Employees where e.Country = country select e;if (context.Connection.State != ConnectionState.Open)context.Connection.Open();Console.WriteLine(query as ObjectQuery).ToTraceString();也可以通过反射(Reflection)和Invoke() 方法,得到相同的结果:Console.WriteLine(query.GetType().GetMethod(ToTraceString).Invoke(query, null);3. 使用eSqlBlast 工具微软也提供了一个免费的工具来帮助学习Entity SQL。eSqlBlast 的下载地址(含有源代码,需要自己编译一下)及其相关介绍(eSqlBlast for VS 2008 SP1):/esql/Release/ProjectReleases.aspx?ReleaseId=991如果懒得编译,可以直接在本文章底部点击下载链接,下载已经编译好的可执行文件。运行界面如下:图片看不清楚?请点击这里查看原图(大图)。Connection 页面用来指定3个元数据文件(CSDL/SSDL/MSL)和数据库连接字符串。数据库连接字符串可以直接从App.config 复制过来。点击Connect 按钮进行连接。Model 页面用来显示所有的EntitySets和EntityTypes。图片看不清楚?请点击这里查看原图(大图)。Query 页面可以输入 Entity SQL脚本,你会注意到eSqlBlast 支持智能提示(IntelliSense),酷吧!目前,Visual Studio 2008 sp1 尚不支持Entity SQL 的职能提示呢。图片看不清楚?请点击这里查看原图(大图)。点击Execute 执行按钮,执行结果将以HTML的格式显示在Results 页面,如下图所示。包括4个部分:Enttiy Command (也就是CommandText 属性值)、Store Command(生成的T-SQL脚本,也就是ToTraceString() 方法产生的脚本)、Record Count(结果集的记录数)、Data(实际记录结果)。图片看不清楚?请点击这里查看原图(大图)。4. 使用免费LINQPad 工具LINQPad 是一个优秀的LINQ 表达式测试工具,原本设计用来执

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论