http://www.cnblogs.com/xlovey/archive/2011/01/03/1924800.html

ADO.NET 实体框架概述

新版本中的 ADO.NET 以新实体框架为特色。它使开发人员可以通过对象模型(而不是逻辑/关系数据模型)专注于数据。实体框架有助于将逻辑数据架构抽象为概念模型,并且允许以多种方式通过对象服务和名为“EntityClient”的新数据提供程序与概念模型交互。

实体框架使用概念层(ConceptualModels)、映射层(Mappings)和逻辑层(StorageModels)将逻辑数据库结构抽象化。EntityClient 的备选项是对象服务。具体地说,实体框架中的对象服务有助于减少开发人员需要编写的数据访问代码的数量。

实体框架组件

实体框架使开发人员可以编写更少的数据访问代码,减少维护,将数据结构抽象化为更易于开展业务(标准化程度较低)的方式,并且有利于数据的持久性。当与 LINQ to Entities结合使用时,由于实体框架从概念模型中生成强类型化类,还有助于降低编译时错误的数量。

实体框架生成开发人员能够依据其编写代码的概念模型。使用名为“EntityClient”的新数据提供程序和名为“Entity SQL”的新语言(类似于 T-SQL)可以直接与该模型交互。EntityClient 具有与熟悉的 ADO.NET 对象类似的模型,使用 EntityConnection 和 EntityCommand 对象返回 DbDataReader。开发人员的另一种方法是通过具有Entity SQL 的 ObjectQuery 对象或 LINQ to Entities 来使用对象服务。对象服务使开发人员可以利用概念模型的生成类,这些生成类提供了强类型化对象和持久性等特性(请参见图 1)。

图 1 实体框架概述

这些数据访问技术使开发人员可以与 EDM 的概念实体交互。EDM 的各个层以 XML 文件形式存在;目前可以通过手动方式(或使用 Visual Studio 中的向导)使用命令行工具 (EDMGEN.EXE) 生成 EDM。

实体数据模型

实体框架的核心位于其模型中。实体框架支持表示数据库中的关系架构的逻辑存储模型。关系数据库通常存储数据的方式与应用程序使用数据的方式不同。通常,这会迫使开发人员按照数据库包含数据的结构检索数据。因此,开发人员通常将数据加载到更适合处理业务规则的业务实体中。在本示例中,以逻辑模型表示关系数据库的构架,业务实体表示概念模型。实体框架使用映射层在模型之间搭建了桥梁。因此,实体框架的模型中有三个处于活动状态的层:

· 概念层

· 映射层

· 逻辑层

这三层允许将数据从关系数据库映射到更加面向对象的业务模型。实体框架提供了使用 XML 文件定义这些层的方法。它还基于概念模型的架构生成了一系列类。可以针对这些类进行编程以直接与数据交互。这提供了抽象级别,因此开发人员可以针对概念模型而不是关系模型进行编程。实体框架可将针对概念模型编码的所有命令映射到逻辑模型中(请参见图 2)。

图 2 设计实体数据模型 (单击该图像获得较大视图)

概念模型是使用概念架构定义语言 (CSDL) 在 XML 文件中定义的。CSDL 定义应用程序的业务层所知道的实体和关系。逻辑模型(表示数据库架构)是使用存储架构定义语言 (SSDL) 在 XML 文件中定义的。例如,您可能在概念模型中有一个实体,该实体实际上从数据库的多个表中派生其数据。概念模型和逻辑模型可按一对一的关系来关联实体。然而,EDM 的功能是它不必以一对一的方式链接实体。映射层(是使用映射架构语言 (MSL) 定义的)实现其他两层彼此之间的映射。此映射使开发人员可以针对概念模型编写代码,并将这些指令映射到逻辑模型。

生成实体数据模型

可以将数据库作为起点生成 EDM。然后,可以手动修改 XML(或者可能使用 Visual Studio 将来版本中可能提供的模型工具)。将 ADO.NET EDM 添加到项目后,向导会指导您完成创建 EDM 的过程。

第一步、创建解决方案“EntityFrameworkTest”和控制台应用程序“EFProjectCA”。

第二步、添加“ADO.NET实体数据模型”,命名为"NorthWindEF.edmx"。

接着选择“从数据库生成”,如果后期采用POCO开发模式,可以选择”空模型“。

到这里就创建成功了。NorthWindEF.edmx包含了CSDL、SSDL、MSL,我们可以通过记事本查看它的结构,也可以复制一份,把扩展名改为xml,在VS2010中打开。

 

分析 CSDL

驻留在 CSDL 文件中的元数据包含一系列实体和关系,其中实体由 EntityType 元素表示,关系由 Association 元素表示。实体包含一系列用于定义实体的标量属性。Key 属性指示对实体很关键的属性。复合关键字通过用空格分隔每个属性名来表示。实体还可以包含名为“NavigationProperty”的一种特殊类型的属性。这定义了如何按照关联从一个实体导航到另一个实体。

<EntityType Name="Customers">

<Key>

<PropertyRef Name="CustomerID" />

</Key>

<Property Name="CustomerID" Type="String" Nullable="false" MaxLength="5" Unicode="true" FixedLength="true" />

<Property Name="CompanyName" Type="String" Nullable="false" MaxLength="40" Unicode="true" FixedLength="false" />

<Property Name="ContactName" Type="String" MaxLength="30" Unicode="true" FixedLength="false" />

...

<NavigationProperty Name="Orders" Relationship="NorthwindModel.FK_Orders_Customers" FromRole="Customers" ToRole="Orders" />

<NavigationProperty Name="CustomerDemographics" Relationship="NorthwindModel.CustomerCustomerDemo" FromRole="Customers" ToRole="CustomerDemographics" />

</EntityType>

以下 CSDL 片段定义了 Customer 及其 Orders 之间的 AssociationSet :

<AssociationSet Name="FK_Orders_Customers" Association="NorthwindModel.FK_Orders_Customers">

<End Role="Customers" EntitySet="Customers" />

<End Role="Orders" EntitySet="Orders" />

</AssociationSet>

AssociationSet 的 End 元素表示关联的参与者。在本示例中,一个 Customers 实体与一个 Orders 实体相关联。根据多重性定义,一个 Customers 实体还可以与任意数量的 Orders 实体相关联。

EntityType 和 Association 元素定义域实体和关系的类型,而 EntitySet 和 AssociationSet 元素定义实体和关系的作用域。逻辑上应组合到一起的所有“集”都包含在 EntityContainer 元素内。

下面的 CSDL 片段显示了 EntityContainer 及其部分内容:

<EntityContainer Name="NorthwindEntities" annotation:LazyLoadingEnabled="true">

<EntitySet Name="Categories" EntityType="NorthwindModel.Categories" />

<EntitySet Name="CustomerDemographics" EntityType="NorthwindModel.CustomerDemographics" />

<EntitySet Name="Customers" EntityType="NorthwindModel.Customers" />

...

<AssociationSet Name="FK_Products_Categories" Association="NorthwindModel.FK_Products_Categories">

<End Role="Categories" EntitySet="Categories" />

<End Role="Products" EntitySet="Products" />

</AssociationSet>

<AssociationSet Name="FK_Orders_Customers" Association="NorthwindModel.FK_Orders_Customers">

<End Role="Customers" EntitySet="Customers" />

<End Role="Orders" EntitySet="Orders" />

</AssociationSet>

...

</AssociationSet>

</EntityContainer>

 

映射到存储

SSDL 文件定义了数据库中关系数据的结构。在本例中,它还使用了 EntityType 和 Association XML 元素来分别声明存在于数据库中的表和外键的结构。SSDL 文件的命名空间是基于 EDM 中所用数据库的名称而设置的,而其 EntityContainer 元素是以数据库架构命名的。EntityContainer 包含一系列 EntitySet 和 AssociationSet 元素,这些元素声明由 EntityType 和 AssociationType 表示的表和关系的实例。对于 SSDL 文件中的每个 EntitySet,数据库中均有一个与之对应的表。

如果从数据库中生成 EDM 并且未对 CSDL 和 SSDL 文件进行修改就立即将其打开,则您会发现这些文件极其相似。这是因为模型是直接从数据库生成的,因此概念模型直接映射到了逻辑存储。MSL 文件包含从 CSDL 到 SSDL 的直接映射。所有针对 EDM 编写的查询均将转换为生成的 SQL 命令。实体框架还支持使用存储过程而不是生成的 SQL 查询。

EntityContainerMapping 元素用于将模型 (CSDL) 映射到存储 (SSDL)。StorageEntityContainer 属性表示存储中 EntityContainer 的名称,而 CdmEntityContainer 属性表示模型中与之相对应的 EntityContainer。将模型的 EntitySet 映射到存储的 EntitySet 需要 EntitySetMapping 元素。TypeName 属性定义模型中 EntitySet 的名称,而 StoreEntitySet 属性定义存储中与之相对应的 EntitySet 的名称。通过 ScalarProperty 元素可将模型中的每个属性映射到存储。

<EntitySetMapping Name="Products">

<EntityTypeMapping TypeName="NorthwindModel.Products">

<MappingFragment StoreEntitySet="Products">

<ScalarProperty Name="ProductID" ColumnName="ProductID" />

<ScalarProperty Name="ProductName" ColumnName="ProductName" />

<ScalarProperty Name="SupplierID" ColumnName="SupplierID" />

<ScalarProperty Name="CategoryID" ColumnName="CategoryID" />

<ScalarProperty Name="QuantityPerUnit" ColumnName="QuantityPerUnit" />

<ScalarProperty Name="UnitPrice" ColumnName="UnitPrice" />

<ScalarProperty Name="UnitsInStock" ColumnName="UnitsInStock" />

<ScalarProperty Name="UnitsOnOrder" ColumnName="UnitsOnOrder" />

<ScalarProperty Name="ReorderLevel" ColumnName="ReorderLevel" />

<ScalarProperty Name="Discontinued" ColumnName="Discontinued" />

</MappingFragment>

</EntityTypeMapping>

</EntitySetMapping>

 

使用 EntityClient

可通过三种不同机制中的任意一种实现对实体框架的概念模型的访问(请参见图 1)。在此,我将介绍 EntityClient,即新的 .NET 数据提供程序。

当 EntityClient 使用自己的名为“Entity SQL”的基于文本的语言与概念模型通信时,会将其从逻辑存储中提取出来。所有使用 EntityClient 执行的Entity SQL 查询均被编译成发送到存储的命令树。查询从概念模型的Entity SQL 到存储的向下转换由实体框架处理。

EntityClient 中的类与常见的 ADO.NET 提供程序中的类相似。例如,使用 EntityCommand 对象执行 EntityClient 查询,这需要 EntityConnection 对象连接到 EDM。当 EntityClient 与 EDM 中的实体交互时,EntityClient 不返回实体的实例而返回 DbDataReader 对象中的所有结果。EntityClient 可以返回一组标准行和列,也可以通过 DbDataReader 返回更复杂的分层数据的表示形式。

示例使用 EntityClient 连接到概念模型并检索来自伦敦的客户列表。EntityConnection 可以接受概念层的完整连接字符串或 App.Config 文件中连接字符串的名称。连接字符串包含元数据文件(CSDL、MSL 和 SSDL 文件)列表,以及存储的专用于数据库的连接字符串信息。

using System.Data;

using System.Data.EntityClient;

using System.Configuration;

...

//string connStr = System.Configuration.ConfigurationManager.ConnectionStrings["NorthwindEntities"].ConnectionString;

//CSharpTestEntities edm = new CSharpTestEntities();

//string connStr = edm.Connection.ConnectionString;

string connStr = "name = NorthwindEntities"; //使用三种方法获取连接字符串

using (EntityConnection conn = new EntityConnection(connStr))

{

string sqlStr = " SELECT VALUE c FROM NorthwindEntities.Customers AS c";

conn.Open();

EntityCommand ecmd = new EntityCommand(sqlStr, conn);

//ExecuteDbDataReader、ExecuteNonQuery 、ExecuteReader 、ExecuteScalar等

EntityDataReader edr = ecmd.ExecuteReader(CommandBehavior.SequentialAccess);

while (edr.Read())

{

Console.WriteLine(edr["CompanyName"]);

}

Console.WriteLine(ecmd.ToTraceString());

}

Console.Read();

 

使用对象服务

与由 EDM 表示的数据进行交互的另一种方法是使用对象服务。通过对象服务,可以加载对象和导航在 EDM 中定义的任何关系。如图 1 所示,对象服务使用 EntityClient 来获取数据。对象服务增添了身份解析,使用 DataSet 时,该身份解析是手动过程。它还提供了对象持久性和事件的跟踪更改以允许显式加载和保存。这将缩短与服务器的往返路程。

对象服务允许直接返回对象列表(即可同时返回投影和定义的实体)。例如,使用对象服务,您可以按 EDM 中的定义检索 List<Customers>。可以检查 Customers 对象,更改值,然后将数据再次保存到数据库中。

如果将投影与对象服务结合使用,则返回的数据将是不可更新的对象。由于投影返回实体的特定属性而不是整个实体,对象服务无法将投影数据的更新再次保存到数据库中。如果您要更新数据,更好的选择是返回整个实体而不是使用投影。

您可以使用对象服务以使用Entity SQL 执行查询,也可以使用 LINQ to Entities 编写查询。下面的示例演示了如何使用对象服务和Entity SQL 进行查询以检索 Customers 列表:

using System.Data.Objects;

...

using (var edm = new NorthwindEntities())

{

string esql = "select value c from NorthwindEntities.Customers as c order by c.CustomerID limit 10";

ObjectQuery<Customers> query = edm.CreateQuery<Customers>(esql);

ObjectResult<Customers> results = query.Execute(MergeOption.NoTracking);

foreach (Customers c in results)

Console.WriteLine(c.CustomerID + ":" + c.CompanyName);

Console.WriteLine(query.ToTraceString());

}

在 EDM 中,EntityContainer 由从 ObjectContext(在本示例中为 northwindContext)继承的类表示。ObjectContext 类实施 ObjectQuery<T> 接口,从而使其可以使用Entity SQL 或 LINQ 创建查询。

CreateQuery 方法接受参数化的Entity SQL 语句,该语句定义了将检索 Customers 实体列表的查询。通过使用 foreach 语句对 ObjectQuery<Customers> 进行迭代时将执行作用于数据库的实际 SQL 语句。

 

使用 LINQ to Entities

可以在Entity SQL 中编写动态查询,并与对象服务一起使用来与 EDM 实体交互。但是,实体框架还可以与使用 LINQ to Entities 强类型化 EDM 类结合使用。例如,在刚才显示的示例中,可以将使用对象服务和Entity SQL 进行查询修改为使用 LINQ to Entities 进行查询,如下所示:

ObjectQuery<Customers> customersList = edm.Customers;

IQueryable<Customers> customersResult = from customers in customersList

where customers.City == "London"

select customers;

foreach (Customers c in customersResult)

Console.WriteLine(c.CustomerID + ":" + c.CompanyName);

此代码示例使用由 C# 3.0 支持的强类型化 LINQ 语法替代了Entity SQL 的所有基于文本的语法。

 

结束语

使用实体框架,开发人员可以通过对象模型(而不是逻辑/关系数据模型)专注于数据。一旦完成 EDM 的设计并将其映射到关系存储后,就可以使用 EntityClient、ObjectServices 和 LINQ 等多种技术与对象交互。

Entity Framework 学习总结之一:ADO.NET 实体框架概述的更多相关文章

  1. ADO.NET Entity Framework学习笔记(3)ObjectContext

    ADO.NET Entity Framework学习笔记(3)ObjectContext对象[转]   说明 ObjectContext提供了管理数据的功能 Context操作数据 AddObject ...

  2. ADO.NET实体框架Entity Framework模型-基于元数据解析

           上一篇简单介绍了EF的XML模型结构,在基于xml解析一文中,主要使用xml查询技术Xpath,XQuery来得到实体模型中相应信息的,由于这种方式在数据库庞大,表关系复杂的情况下,有诸 ...

  3. Entity Framework学习笔记

    原文地址:http://www.cnblogs.com/frankofgdc/p/3600090.html Entity Framework学习笔记——错误汇总   之前的小项目做完了,到了总结经验和 ...

  4. Entity Framework 学习

    Entity Framework 学习初级篇1--EF基本概况 Entity Framework 学习初级篇2--ObjectContext.ObjectQuery.ObjectStateEntry. ...

  5. Entity Framework 学习整理

    MSDN: http://msdn.microsoft.com/en-us/data/aa937723 台湾博客: http://www.dotblogs.com.tw/yc421206/ http: ...

  6. Entity Framework 学习整理(分播客整理)

    MSDN: http://msdn.microsoft.com/en-us/data/aa937723 台湾博客: http://www.dotblogs.com.tw/yc421206/ http: ...

  7. Entity Framework 学习中级篇1—EF支持复杂类型的实现

    本节,将介绍如何手动构造复杂类型(ComplexType)以及复杂类型的简单操作. 通常,复杂类型是指那些由几个简单的类型组合而成的类型.比如:一张Customer表,其中有FristName和Las ...

  8. Entity Framework 学习初级篇4--Entity SQL

    Entity SQL 是 ADO.NET 实体框架 提供的 SQL 类语言,用于支持 实体数据模型 (EDM).Entity SQL 可用于对象查询和使用 EntityClient 提供程序执行的查询 ...

  9. Entity Framework学习初级篇2

    Entity Framework 学习初级篇2--ObjectContext.ObjectQuery.ObjectStateEntry.ObjectStateManager类的介绍 本节,简单的介绍E ...

随机推荐

  1. 泛型类型的协变(covariant)和逆变

    官网:http://msdn.microsoft.com/zh-cn/library/dd799517.aspx 原文链接:http://book.51cto.com/art/201112/30857 ...

  2. R 语言实现牛顿下降法

    凸是一个很好的性质.如果已经证明了某个问题是凸的,那这个问题基本上算是解决了. 最近在解决一个多目标优化的问题.多目标的问题往往是非凸的.好在能够知道这个问题的近似解大概是多少.这样这个多目标优化的问 ...

  3. C# 杂项

    1,函数访问等级必须高于参数等级,如函数等级是PUBLIC,则参数必须高于等于PUBLIC,若为INTERNAL 则不行.INTERNAL 低于PUBLIC, 用于同一个程序集内引用,PUBLIC则可 ...

  4. Edittext焦点处理

    <LinearLayout android:focusable="true" android:layout_width="0dp" android:lay ...

  5. 缓存算法之belady现象

    前言 在使用FIFO算法作为缺页置换算法时,分配的缺页增多,但缺页率反而提高,这样的异常现象称为belady Anomaly. 虽然这种现象说明的场景是缺页置换,但在运用FIFO算法作为缓存算法时,同 ...

  6. Android -- 创建数据库到SD卡

    SQLite 系统自带的SQLite是通过SQLiteOpenHelper实现的,而SQLiteOpenHelper是将数据库存储到/data/data/包名/databasas,这样做的话在没有ro ...

  7. OpenGL、Open Inventor、WebGL、Three.js、ARToolkit、JSARToolkit

    [准备看的] http://www.hewebgl.com/ http://www.linuxdiyf.com/viewarticle.php?id=399205 http://blog.sina.c ...

  8. LeetCode:Word Break(DP)

    题目地址:http://oj.leetcode.com/problems/word-break/ 简单的动态规划问题,采用自顶向下的备忘录方法,代码如下: class Solution { publi ...

  9. 利用JS跨域做一个简单的页面访问统计系统

    其实在大部分互联网web产品中,我们通常会用百度统计或者谷歌统计分析系统,通过在程序中引入特定的JS脚本,然后便可以在这些统计系统中看到自己网站页面具体的访问情况.但是有些时候,由于一些特殊情况,我们 ...

  10. 如何优雅的写一篇安利文-以Sugar ORM为例

    前言 我最近喜欢把写的十分优美的技术文章叫做安利文.首先,文章必须是原创而非软广:其次,阅读之后不仅能快速吸纳技术要点并入门开发,还能感同身受的体会作者热情洋溢的赞美和急于分享心得体验的心情,让人感觉 ...