优雅地使用EntityFramework综述Word下载.docx

上传人:b****4 文档编号:6446009 上传时间:2023-05-06 格式:DOCX 页数:16 大小:98.37KB
下载 相关 举报
优雅地使用EntityFramework综述Word下载.docx_第1页
第1页 / 共16页
优雅地使用EntityFramework综述Word下载.docx_第2页
第2页 / 共16页
优雅地使用EntityFramework综述Word下载.docx_第3页
第3页 / 共16页
优雅地使用EntityFramework综述Word下载.docx_第4页
第4页 / 共16页
优雅地使用EntityFramework综述Word下载.docx_第5页
第5页 / 共16页
优雅地使用EntityFramework综述Word下载.docx_第6页
第6页 / 共16页
优雅地使用EntityFramework综述Word下载.docx_第7页
第7页 / 共16页
优雅地使用EntityFramework综述Word下载.docx_第8页
第8页 / 共16页
优雅地使用EntityFramework综述Word下载.docx_第9页
第9页 / 共16页
优雅地使用EntityFramework综述Word下载.docx_第10页
第10页 / 共16页
优雅地使用EntityFramework综述Word下载.docx_第11页
第11页 / 共16页
优雅地使用EntityFramework综述Word下载.docx_第12页
第12页 / 共16页
优雅地使用EntityFramework综述Word下载.docx_第13页
第13页 / 共16页
优雅地使用EntityFramework综述Word下载.docx_第14页
第14页 / 共16页
优雅地使用EntityFramework综述Word下载.docx_第15页
第15页 / 共16页
优雅地使用EntityFramework综述Word下载.docx_第16页
第16页 / 共16页
亲,该文档总共16页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

优雅地使用EntityFramework综述Word下载.docx

《优雅地使用EntityFramework综述Word下载.docx》由会员分享,可在线阅读,更多相关《优雅地使用EntityFramework综述Word下载.docx(16页珍藏版)》请在冰点文库上搜索。

优雅地使用EntityFramework综述Word下载.docx

实体框架使用这些基于XML的模型和映射文件将对概念模型中的实体和关系的创建、读取、更新和删除操作转换为数据源中的等效操作。

EDM甚至支持将概念模型中的实体映射到数据源中的存储过程。

它提供以下方式用于查询EDM并返回对象:

LINQtoEntities--提供语言集成查询(LINQ)支持用于查询在概念模型中定义的实体类型。

EntitySQL--与存储无关的SQL方言,直接使用概念模型中的实体并支持诸如继承和关系等EDM功能。

查询生成器方法--可以使用LINQ风格的查询方法构造EntitySQL查询。

下图演示用于访问数据的实体框架体系结构:

1.1.ORM的历史

如何正确地选用钢材,既经济又能满足性能要求,以及正确选择热处理工艺。

1.2.开始使用EntityFramework

图11端淬法测定示意图

2.创建实体模型

2.1.创建模型概述

2.2.使用ModelFirst创建模型

2.3.使用DatabaseFirst创建模型

2.4.使用CodeFirst创建模型

2.4.1.数据库已存在情景下使用CodeFirst创建模型

2.4.2.数据库不存在情景下使用CodeFirst创建模型

3.配置实体模型

3.1.概述

3.2.配置实体的属性

3.2.1.使用DataAnnotation配置

3.2.2.使用FluentAPI配置

3.3.配置实体的关系

3.3.1.使用DataAnnotation配置

3.3.2.使用FluentAPI配置

3.4.配置复杂类型的模型

3.4.1.如何使用复杂类型(ComplexType)

3.4.2.将实体映射到多个表(实体拆分)

3.4.3.将多个实体映射到一个表(表拆分)

4.使用EF管理Database

4.1.配置Database的位置

4.1.1.使用连接字符串配置

4.1.2.使用配置文件配置

4.1.3.使用连接字符串的名称配置

4.1.4.重用数据库链接

4.1.5.使用ConnectionFactory管理EF的数据库链接

4.2.

Database的初始化

4.2.1.设置Database的初始化器

初始化器的介绍

自定义初始化器

从配置文件中设置Database的初始化器

4.2.2.手工控制Database的初始化

4.2.3.使用初始化器插入种子数据

使用模型插入种子数据

使用Sql脚本插入种子数据

4.3.使用DbContext

4.3.1.DbContext简介

4.3.2.DbContext与ObjectContext的关系

ObjectContext封装.NETFramework和数据库之间的连接。

此类用作“创建”、“读取”、“更新”和“删除”操作的网关。

它是以对象(这些对象是概念模型中定义的实体类型的实例)的形式与数据进行交互的主要类。

ObjectContext类的实例封装以下内容:

·

数据库的连接,以EntityConnection对象的形式封装。

描述该模型的元数据,以MetadataWorkspace对象的形式封装。

用于管理缓存中持久保存的对象的ObjectStateManager对象。

成员参考:

4.3.3.自定义DbContext

4.3.4.DbContext的生命周期

4.3.5.DbContext对数据库连接的管理

DbContext自动管理数据库连接

4.3.6.DbContet的线程安全

5.查询数据

5.1.POCO对象

默认情况下,当你使用数据库优先或者模型优先开发方法的时候,你的数据模型对象需要派生自EntityObject类,通过它提供EF功能。

这意味着这些类不能是持久性无感知(persistenceignorant)的,所以不能符合领域驱动开发的要求。

所有的EF开发方法都支持使用POCO类,由于不需要派生自EntityObject,所以,这样的类是持久性无感知的。

5.2.模型实体的版本跟踪

EF通过比较实体的当前值与原始值来决定实体如何变化(依此来决定发送到数据库的更新)。

在查询或者连接的时候原始值被保存起来。

导致自动变化跟踪监测的一些方法如下:

DbSet.Find

DbSet.Local

DbSet.Remove

DbSet.Add

DbSet.Attach

DbContext.SaveChanges

DbContext.GetValidationErrors

DbContext.Entry

DbChangeTracker.Entries

如果你跟踪大量的实体,而且在循环中多次调用上面提到的方法,通过使用AutoDetectChangesEnabled属性暂时关闭变化检测,可以得到显著的性能提升。

Don’tforgettore-enabledetectionofchangesaftertheloop—We'

veusedatry/finallytoensureitisalwaysre-enabledevenifcodeintheloopthrowsanexception.Analternativetodisablingandre-enablingistoleaveautomaticdetectionofchangesturnedoffatalltimesandeithercallcontext.ChangeTracker.DetectChangesexplicitlyorusechangetrackingproxiesdiligently.Bothoftheseoptionsareadvancedandcaneasilyintroducesubtlebugsintoyourapplicationsousethemwithcare.

5.2.1.无跟踪查询

Sometimesyoumaywanttogetentitiesbackfromaquerybutnothavethoseentitiesbetrackedbythecontext.Thismayresultinbetterperformancewhenqueryingforlargenumbersofentitiesinread-onlyscenarios.ThetechniquesshowninthistopicapplyequallytomodelscreatedwithCodeFirstandtheEFDesigner.

AnewextensionmethodAsNoTrackingallowsanyquerytoberuninthisway.Forexample:

using(varcontext=newBloggingContext())

{

//Queryforallblogswithouttrackingthem

varblogs1=context.Blogs.AsNoTracking();

//Queryforsomeblogswithouttrackingthem

varblogs2=context.Blogs

.Where(b=>

b.Name.Contains("

.NET"

))

.AsNoTracking()

.ToList();

}

当数据库上下文从数据库获取数据行然后表示为实体的时候,默认情况下,会保持对内存中实体对象是否与数据库中数据同步的追踪。

内存中的数据作为缓存,当你更新实体的时候被用来更新。

这个缓存在Web应用程序中通常没有必要,因为上下文对象的实例生命期很短(对于每一次请求创建一个新的,然后释放),在实体被再次使用之前数据库上下文读取的实体对象已经被释放了。

你可以通过AsNoTracking方法来指定上下文对象是否追踪实体对象。

使用这个方法常见的场景如下:

对于查询大量数据的查询来说,关闭追踪可以提高性能。

你更希望重新连接一个对象用来更新,尽管基于不同的目的以前获取过同样的对象。

由于数据库上下文已经追踪了这个实体,你就不能连接你希望修改的实体。

防止出现这种情况的一种方式就是在原来的查询中使用AsNoTracking选项。

EntityFrameworkCodeFirst通过DbContext.ChangeTracker对实体对象的变动进行跟踪,实现跟踪的方式有两种:

变动跟踪快照和变动跟踪代理。

  变动跟踪快照:

前面几篇随笔的示例都是通过实体对象变动快照跟踪来实现数据操作的,POCO模型不包含任何逻辑去通知EntityFramework实体类属性的变动。

EntityFramework在第一次对象加载到内存中时进行一次快照,添加快照发生在返回一次查询或添加一个对象到DbSet中时。

当EntityFramework需要知道对象的变动时,将先把当前实体与快照中的对象进行扫描对比。

实现扫描对比的方法是调用DbContext.ChangeTracker的DetectChanges方法。

  变动跟踪代理:

变动跟踪代理是一种会主动通知EntityFramework实体对象发生变动的机制。

如:

延迟加载的实现方式。

要使用变动跟踪代理,需要在定义的类结构中,EntityFramework可以在运行时从POCO类中创建动态类型并重写POCO属性。

动态代理就是一种动态类型,包含重写属性和通知EntityFramework实体对象变动的逻辑。

EntityFramework之CodeFirst方式中能够自动调用DbContext.ChangeTracker.DetectChanges的方法:

  ◊DbSet.Add

  ◊DbSet.Find

  ◊DbSet.Remove

  ◊DbSet.Attach

  ◊DbSet.Local

  ◊DbContext.SaveChanges

  ◊DbContext.GetValidationErrors

  ◊DbContext.Entry

  ◊DbChangeTracker.Entries

  ◊任何在DbSet上进行LINQ的查询

  1、控制什么时间调用DetectChanges

  大部分的实例对象的变动调整需要在EntityFramework进行SaveChanges时才会知道,但也可以根据需要调用变动跟踪获取当前对象的状态。

EntityFrameworkCodeFirst的DbContext.DetectChanges在检测实例对象的变动时,大部分情况不会有性能的问题。

但当有大量的实例对象在内存中,或DbContext有大量的操作时,自动的DetectChanges行为可能会一定程度的影响性能。

EntityFramework提供关闭自动的DetectChanges的功能,在需要的时候进行手动调用。

using(varctx=newPortalContext())

{

ctx.Configuration.AutoDetectChangesEnabled=false;

varprovince=ctx.Provinces.Find

(1);

province.ProvinceName="

测试"

;

Console.WriteLine("

BeforeDetectChanges:

{0}"

ctx.Entry(province).State);

ctx.ChangeTracker.DetectChanges();

AfterDetectChanges:

代码运行结果:

Unchanged

Modified

2、获取不带变动跟踪的实体查询

  在一些情况下,我们只需要查询返回一个只读的数据记录,而不会对数据记录进行任何的修改。

这种时候不希望EntityFramework进行不必要的状态变动跟踪,可以使用EntityFramework的AsNoTracking方法来查询返回不带变动跟踪的查询结果。

5.3.模型实体的代理对象

为POCO实体类型创建实例时,实体框架常常为充当实体代理的动态生成的派生类型创建实例。

此代理重写实体的某些虚拟属性,这样可在访问属性时插入挂钩,从而自动执行操作。

例如,此机制用于支持关系的延迟加载。

当EF创建实体对象的时候(例如,在执行查询的时候),EF经常会创建动态生成的派生自实体的代理对象。

代理重写了实体的虚拟属性来插入在访问属性的时候自动执行的钩子。

例如,这种机制用来支持延迟加载或者关联。

多数时候你并不能察觉使用了代理,除了下面的情况之外:

有一些场景,你需要阻止EF创建代理实例。

例如,序列化非代理的对象实例可能比序列化代理对象实例更加有效。

当使用new操作符实例化实体的时候,你并没有得到代理实例。

这意味着你不能获得诸如延迟加载以及自动追踪的能力。

一般没有问题,通常并不需要延迟加载,因为你在创建数据库中并不存在的实体。

在将实体标记为Added状态的时候,也不需要追踪。

然而,如果你需要延迟加载,需要改变追踪,就可以通过DbSet类的Create方法来创建实体代理对象。

可能需要通过代理类型对象实例获取真实实体类型。

可以使用ObjectContext类的GetObjectType方法来通过代理对象获取实际对象。

5.3.1.禁用代理

有时需要禁止实体框架创建代理实例。

例如,人们通常认为序列化非代理实例要比序列化代理实例容易得多。

可通过清除ProxyCreationEnabled标记来关闭代理创建功能。

上下文的构造函数便是可执行此操作的一个位置。

例如:

publicclassBloggingContext:

DbContext

publicBloggingContext()

{

this.Configuration.ProxyCreationEnabled=false;

}

publicDbSet<

Blog>

Blogs{get;

set;

Post>

Posts{get;

请注意,在无需代理执行任何操作的情况下,EF不会为类型创建代理。

这意味着,也可以通过使用封装和/或没有虚拟属性的类型,避免生成代理。

5.3.2.显式创建代理实例

通过使用DbSet的Create方法执行此操作。

varblog=context.Blogs.Create();

如果要创建派生实体类型的实例,可使用Create的通用版本。

using(varcontext=newBloggingContext())

varadmin=context.Users.Create<

Administrator>

();

请注意,Create方法不将已创建的实体添加或附加到上下文。

请注意,如果因为实体代理类型不执行任何操作而导致创建的实体代理类型不包含任何值,Create方法将仅创建实体类型本身的实例。

例如,如果实体类型已封装和/或没有虚拟属性,则Create将仅创建实体类型的实例。

5.3.3.从代理类型获取实际实体类型

代理类型的名称类似如下所示:

System.Data.Entity.DynamicProxies

.Blog_5E43C6C196972BF0754973E48C9C941092D86818CD94005E9A759B70BF6E48E6

可通过使用ObjectContext中的GetObjectType方法,查找此代理类型的实体类型。

varblog=context.Blogs.Find

(1);

varentityType=ObjectContext.GetObjectType(blog.GetType());

请注意,如果传递给GetObjectType的类型是非代理类型的实体类型的实例,则仍将返回实体的类型。

这意味着,始终可以使用此方法获取实际的实体类型,而不用再检查类型是否是代理类型。

5.3.4.代理类加载的前提

TheEntityFrameworkcreatesproxiesforPOCOentitiesiftheclassesmeettherequirementsdescribedbelow.POCOentitiescanhaveproxyobjectsthatsupportchangetrackingorlazyloading.Youcanhavelazyloadingproxieswithoutmeetingtherequirementsforchangetrackingproxies,butifyoumeetthechangetrackingproxyrequirements,thenthelazyloadingproxywillbecreatedaswell.YoucandisablelazyloadingbysettingtheLazyLoadingEnabledoptiontofalse.

简单来说代理类是跟踪和懒加载的前提。

Foreitheroftheseproxiestobecreated:

代理类的前提

Acustomdataclassmustbedeclaredwithpublicaccess.必须是开放(public)申明

Acustomdataclassmustnotbesealed(NotInheritableinVisualBasic)不能是sealed申明

Acustomdataclassmustnotbeabstract(MustInheritinVisualBasic).不能是抽象类

Acustomdataclassmusthaveapublicorprotectedconstructorthatdoesnothaveparameters.UseaprotectedconstructorwithoutparametersifyouwanttheCreateObjectmethodtobeusedtocreateaproxyforthePOCOentity.CallingtheCreateObjectmethoddoesnotguaranteethecreationoftheproxy:

thePOCOclassmustfollowtheotherrequirementsthataredescribedinthistopic.必须有无参的构造函数

TheclasscannotimplementtheIEntityWithChangeTrackerorIEntityWithRelationshipsinterfacesbecausetheproxyclassesimplementtheseinterfaces.不能继承自这两

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 自然科学 > 物理

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2