学习Entity Framework技术期间查阅的优秀文章,出于以后方便查阅的缘故,转载至Blog,可查阅原文:http://blog.csdn.net/bitfan/article/details/12887007

在深入学习某项技术之前,应该努力形成对此技术的总体印象,并了解其基本原理,本文的目的就在于此。

一、理解EF数据模型

EF本质上是一个ORM框架,它需要把对象映射到底层数据库中的表,为此,它使用了三个模型来描述这种映射关系。

(1)概念模型(Conceptual Model):主要体现为一组可以被应用程序直接使用的类。这些类也是我们在程序中直接使用的类,通常称之为“实体(Entity)”

(2)存储模型(Storage Model):主要体现为一组与底层数据存储介质(比如数据库系统)直接对应的类。

(3)概念-存储模型映射(Conceptual- Storage Mapping),解决“概念模型”中的类如何与“存储模型”中的类相互对应的问题。

(2)和(3)中的类型由EF内部使用,在实际开发中通常触及不到。

所有这三种模型都集中放在名为edmx文件中,以XML方式表达。

VisualStudio提供了一个向导,完成从现有数据库到EF数据模型间的映射转换工作:

当此向导完成之后,EF成功地在数据库与程序中使用的对象之间建立了以下对应关系:

关系数据库的世界

数据库应用程序的世界

数据库

DbContext类

DbContext中的DbSet<实体类名>

表间的关联

实体类之间的关联

表中的字段

实体类的公有属性

表中的单条记录

单个实体类的对象

视图

DbContext中的DbSet<视图名称>

存储过程

DbContext中的公有方法

可以在Visual Studio 的模型浏览面板中看到EF数据模型的概念模型和存储模型,如果直接以xml格式打开.edmx文件,可以看到“原汁原味”的全部三大数据模型。

Visual Studio提供的EF向导不仅生成了上述三大数据模型,还使用T4代码模板(其文件扩展名为.tt)直接生成了相应实体类,还有一个派生自DbContext的子类,在其中包容了所有实体集合属性和导入的存储过程等数据库元素。这一DbContext子类是我们使用EF开发程序的核心类型。

在解决方案资源管理器中双击“edmx”文件将打开EF设计器,这是一个很强悍的工具,几乎所有的调整数据映射关系的工作都可以使用它来完成。

如果基于Database First或Model First方式开发,那么EF设计器是天天要打交道的东西。其操作方式很简单:右击设计器,从弹出菜单中选择相应命令

EF设计器提供的各种命令和具体使用方法有很多资料介绍,在此就不废话了。

二、使用EF访问数据库的基本方式

EF中可以使用以下四种方式访问数据库:

Entity SQL是专门为EF设计的一种查询语言,非常类似于通用的关系型数据库查询语言SQL,但它返回的数据都是在EF“概念模型”中所定义的,而非数据库中数据的“真实模样”。

LINQ to Entities可以看成是LINQ  to  Objects的一个“变种”,通过LINQ来查询EF数据模型。它在底层使用“对象服务(Object services)”来完成其功能。对象服务是一组用于查询实体数据模型的类,它可以将这些查询结果转换为强类型的CLR对象。

不管是使用Entity SQL还是LINQ to Entities,最终都是依赖“Entity Client”来完成其工作的。

Entity Client包容一组类,比如EntityConnection、EntityDataReader等,与ADO.NET对象模型非常类似,其功能也类似。Entity Client会将对数据的CRUD请求转发给ADO.NET数据提供者(ADO.NET Provider)组件,由其将相关SQL命令直接地发送给数据库。

在实际开发中,大家都使用LINQ to Entities和针对IEnumerable<T>/IQueryable<T>的一组扩展方法完成数据查询工作,几乎不会有人直接使用Entity SQL和 Entity Client。

下图展示了数应用程序运行过程中EF查询的内部处理流程:

可以看到,使用EF的数据查询从发出到真正执行要经过两次“命令树(Command Tree)转换”,而从数据库中读取的数据,也要经历从DbDataReader-->EntityDataReader-->IEnmerable<T>的转换。虽然EF采用了缓存、预编译等手段提升性能,但与ADO.NET相比,由于中间处理环节更多,整个查询处理流程中参与的对象也更多,因此总体性能一般比不上ADO.NET,并且会占用更多的内存,这也我们是在享用EF带来的方便的同时,所需要付出的代价。

另外,由于所有查询最终还是要转换为SQL命令,因此,有些LINQ to Objects可用的扩展方法,比如Last(),在EF中将不能用,因为EF不知道如何把它们翻译成底层数据库支持的SQL命令。

三、三种开发模式的PK

EF支持三种开发模式:

Code First、Database First和Model First。

到底应该用那一种模式是令人纠结的问题。

方式一:Code First

对于初次接触的人,EF的Code First实在很有点魔幻色彩。下面就让我们来体会一下。

创建两个类:Book(书)和BookReview(书评)。一本书可以有多条书评,因此,它们是一对多的关系:

public class Book{public virtual int Id {get;set;}public virtual string Name { get; set; }public virtual List<BookReview> Reviews { get; set; }}public class BookReview{public int Id{get;set;}public int BookId { get; set; }public virtual string Content { get; set; }public virtual Book AssoicationWithBook { get; set; }}

好了,现在创建一个派生自DbContext的子类:

public class BookDb : DbContext{public DbSet<Book> Books { get; set; }public DbSet<BookReview> Reviews { get; set; }}

现在可以在程序中随意写几行代码从数据库中提取数据:

static void Main(string[] args){using (var context = new BookDb()){Console.WriteLine("数据库中有{0}本书",context.Books.Count());}}

运行一下,如果计算机上安装有SqlExpress,那么或者是在应用程序文件夹,或者是打开SQL Server Management Studio(SSME)查看本机SQLServer,你就会发现,数据库己经创建好,其中的表及表的关联也帮助你完成了:

貌似我什么也没干,一切就OK了,神奇啊!

现在修改Book类,给它添加一个Authors属性,代表书的作者:

public class Book{public virtual int Id {get;set;}public virtual string Name { get; set; }public virtual string Authors { get; set; }public virtual List<BookReview> Reviews { get; set; }}

有了前面良好的第一印象,你一定以为只要再次运行程序,底层数据库就会自动更新,然而,EF会给你当头一棒让你清醒:

很明显,因为你修改了实体类,数据库结构也需要修改,比较郁闷的是,你不能打开创建好的数据库直接修改,而需要使用一个名为“数据库迁移(Database Migration)”的功能,采用两种方式(自动迁移和手动迁移)之一完成。

以自动迁移为例:

首先从从Tools菜单中打开Package Manager Console,然后键入:

enable-migrations –EnableAutomaticMigrations

上述命令会在项目中添加一个Migrations文件夹,其中会有一个Configuration类,为了方便,你需要在其构造函数中添加“AutomaticMigrationDataLossAllowed = true;”一句,让其自动重建数据库时不理会可能的数据丢失:

internal sealed class Configuration :DbMigrationsConfiguration<EFCodeFirst.BookDb>{public Configuration(){AutomaticMigrationsEnabled = true;AutomaticMigrationDataLossAllowed = true;}……}

好了,现在运行update-database命令更新数据库:

再次运行程序,现在将一切OK。

以后每次更改实体类,都必须手动运行update-database命令更新数据库。

手动迁移方式与自动迁移基本一致,不同之处在于它会记录每次更新的情况,从而允许回滚数据库到某个“较老”的版本。

自动方式比较适合于单个人写的应用。而手动方式可以控制数据库结构的更新,比较适合于团队开发。

Code First模式的优点。

从上面的介绍,可以看到Code First有着突出的优点。

(1)是代码清洁,添加自定义逻辑容易。

这是使用Code First最大的好处

特别是在诸如WPF这种可以保持长连接的桌面应用中,可以让实体类实现INotifyProperty接口,将它们放入ObservableCollection中作为UI界面的绑定数据源,便可以充分利用WPF的数据绑定和EF自动维持实体状态的特点,大幅度地削减代码。

(2)易于实现继承

Code First在实现继承上非常方便,如果数据实体中有大量的继承的情况,使用Code First很方便,但需要注意的是Code First在生成数据库表时,默认使用“TPH:Table Per Hierarchy”方式,把父类子类塞到同一张表中,并在表中添加一个Discriminator字段,表明此记录所属的具体类型。

以下是CodeFirst为拥有继承关系的两个Parent/Child类生成的数据库表,可以看到,Discriminator字段保存了具体的数据类型。

有些朋友问能否把Discriminator字段名给改掉,很遗憾,我没发现可以修改它的方法。

很明显,Code First采用的这种实现策略违反了关系数据库设计范式,对大项目来说,这不易于维护数据的一致性。

实现继承的另外一种方式是TPT(table pertype ),不管子类父类,每个类型一张表。

比如有三个类,Instruct和Student派生自Person,若采用TPT策略,EF将生成三个表,并创建以下的关联:

对于TPH,手写SQL代码很容易,性能高,但对于TPT,EF在生成SQL命令时会产生许多Inner Joint,性能低,另外,对于这种方式存储的数据,手写SQL代码比较麻烦。

Database First和Model First默认情况下都是采用TPH的。

我的建议:除非两实体间确实是IS_A关系,并且在中间层需要使用多态,在“数据存取层(DAL)”尽量少用继承,别自找麻烦

(3)一些开发高手们还为EF提供了一个EntityFramework Power Tools,这一工具增强了Code First的不少功能,比如它可以从现有数据库直接逆向生成实体类代码,之后就可以修改这些代码,为Code First方式进行开发省去了不少编码工作。同时,它还能为编写的实体类代码生成只读的数据模型视图,以图形的方式展示出实体类间的关联。

Code First存在的问题

CodeFirst试图“用代码搞掂一切”,其问题在于以下几点:

(1)当Model改变时,往往需要编写代码实现数据库的更改,远不如直接使用数据库所提供的工具修改数据库安全和直观,至少丢失数据的可能性小了很多。

(2)当数据实体间有复杂的关联时,需要使用Fluent API手动编写不少代码定义类之间的关联,这实在麻烦。

(3)对数据库表和关联属性的一些微调(比如改改字段名字,修改字段长度限制等),使用数据库设计工具能轻易实现,但Code First只能通过代码来完成,而且必须使用EF的数据迁移特性,这实在麻烦,整个过程还容易出错。

简而言之,Code First应用的场景是:快速开发,迅速迭代

方式二:Database First

这是EF从1.0开始就支持的特性,其思路是:先设计并建好数据库,然后使用Visual Studio的向导创建EF数据模型并生成实体类代码。

这是最成熟稳定的方式,其设计器相当地完善,基本上能满足实际开发中的各种需求。

我个人认为这是开发正式项目最合适的方式。

当然,DatabaseFirst也有一些问题,主要是需要定制时会有些麻烦。比如:

(1)要想给实体类或生成的DbContext子类添加一些自定义的逻辑,需应用分部类,因为每次更新数据模型,这些代码都会被设计器覆盖并重写。

(2)生成的实体类中不包括任何Data Annotation(所谓“Data Annotation”就是附在实体类代码上的诸如[Required]之类的东东),因此它需要被转换为另一个类,才能方便地在诸如ASP.NET MVC之类的项目中使用(比如ASP.NET MVC项目中的视图模型(ViewModel)类往往需要有Data Annotation,以配合jQuery Validation插件生成网页上的数据验证代码)。

(3)默认情况下实体类与edmx文件放在同一个项目中,想将实体类分离到独立的项目,需要完成一些额外的配置工作(主要是把T4模板文件移到另一个项目,这需要适当地修改T4模板文件中的代码以保证文件路径引用正确)。

方式三:Model First

这种模式是先在可视化设计器中创建实体和它们间的关联,然后设计器生成SQL命令并保存于一个SQL文件中,通过执行这一SQL文件完成数据库的创建和修改工作

我个人感觉:

这种方式最适合于全新开发的项目,从系统分析开始,逐步分析建立和完善领域模型,之后可以立即创建数据库,如果模型有修改,重新生成一个SQL文件,再执行一次即可,非常适合于新项目OOAD阶段的需要。

当进入OOP阶段时,由于数据库己经存在,就可以很方便地转用Database First方式,整个过程流畅自然。

三种模式PK结果:

Code First:对于小的或用于试验的项目,特别是像我经常要讲课的,教学实例使用Code First开发就比较合适,当程序运行时数据库自动生成,比较省事。

DB First:最为成熟,是正规项目的首选方式,因为是由开发者自己(而不是通过一堆“不太可靠”的代码)直接操作数据库,整个过程高度可控,能很好地保证数据安全,贯彻了“数据比代码重要”的理念。

Model First:当开始一个全新的项目,既没有DB,也没有代码时则非常好,是OOAD的好工具,需要时甚至可以直接生成创建各种不同类型数据库(比如MySQL)的SQL代码!

转载于:https://www.cnblogs.com/colder/p/4188619.html

[转]Entity Framework走马观花之把握全局相关推荐

  1. Entity Framework走马观花之把握全局

    Entity Framework走马观花 之 把握全局 ========================================= 这是一个系列文章 上一篇<Entity Framewo ...

  2. Entity Framework 6新特性:全局性地自定义Code First约定

    2012年12月11日,Entity Framework已经发布了Entity Framework 6 Alpha2,因项目需要,目前已使用了其中的两个特性,今天就来介绍一下第一个特性:全局性地自定义 ...

  3. 【EF】Entity Framework 6新特性:全局性地自定义Code First约定

    应用场景 场景一:EF Code First默认使用类名作为表名,如果我们需要给表名加个前缀,例如将类名Category映射到表Shop_Category.将Product映射到Shop_Produc ...

  4. 《你必须掌握的Entity Framework 6.x与Core 2.0》正式出版感想

    前言 借书正式出版之际,完整回顾下从写博客到写书整个历程,也算是对自己近三年在技术上的一个总结,整个历程可通过三个万万没想到来概括,请耐心阅读. 写博.写书完整历程回顾 从2013年12月注册博客园账 ...

  5. Entity Framework Core 2.0的新特性

    虽然EF Core 2.0存在大量槽点,但是它也给出了不少亮点.在本文中,我们将介绍这次发布版的部分亮点. \\ 数据库表切分(Table Splitting) \\ ORM常被吐槽是总是对所请求数据 ...

  6. Entity Framework在Asp.net MVC中的实现One Context Per Request(附源码)

    上篇中"Entity Framework中的Identity map和Unit of Work模式", 由于EF中的Identity map和Unit of Work模式,EF体现 ...

  7. Entity Framework Core 2.0 特性介绍和使用指南

    前言 这是.Net Core 2.0生态生态介绍的最后一篇,EF一直是我喜欢的一个ORM框架,随着版本升级EF也发展到EF6.x,Entity Framework Core是一个支持跨平台的全新版本, ...

  8. Entity Framework Core 3.1 和 Entity Framework 6.4 发布

    目前,Entity Framework Core 3.1 和 Entity Framework 6.4 已正式发布. EF Core 3.1的获取方式 EF Core 3.1 作为一组 NuGet 软 ...

  9. Entity Framework Core 实现全局查询过滤

    作者 | 喵叔 责编 | 刘静 出品 | CSDN(ID:CSDNnews) 微软在 Entity Framework Core 2+ 中引入了全局查询过滤器,简化了构建多租户应用程序和实体软删除的复 ...

最新文章

  1. 数据库安装时挂起问题
  2. OPENCV已知内参求外参
  3. mysql custom_MySQL安装教程
  4. asp和php数据库怎么区分,asp与php的数据库有哪些区别
  5. 升级 Vue3 大幅提升开发运行效率
  6. 【Python】使用 eval 实现反射
  7. html 常见hack,针对主流浏览器的CSS-HACK写法及IE常用条件注释
  8. Oracle 数据库中较为复杂或典型的 SQL 语句的解读
  9. 一文教你学会需求分析与管理
  10. [CUDA OpenCV]GPU加速的计算机视觉学习资源下载
  11. “打击式教育”盛行?数据分析剖析“中式父母”的“打压式教育”
  12. 基于实验数据的轮胎模型
  13. linux部署java命令
  14. 蘑菇街基于Docker的私有云实践
  15. AMTEmu v0.9.2
  16. 重装系统 winserver2008 R2 激活以及优化
  17. 基于89C51单片机的智能语音拨号电话
  18. docker修改redis配置文件
  19. 零基础步入数据分析岗,应该怎么开始?
  20. 屏幕录像专家录制超清视频教程-王西猛-专题视频课程

热门文章

  1. python一个月能学成嘛-学过 Python 的人没有告诉你,年入百万有多难
  2. python学费多少-2020年10月徐州学python要多少学费
  3. 零基础可以学python吗-零基础可以学会python吗?python好学吗?
  4. python基础教程书籍推荐-入门python有什么好的书籍推荐?
  5. python学起来难不难-自学Python很难吗,为何会看不进去!
  6. python爬虫代码1000行-Python爬虫教程(16行代码爬百度)
  7. python语言入门编程猫-少儿编程语言Python入门课程,尽在厦门编程猫
  8. 用python写脚本看什么书-终于知晓python编写脚本入门教程
  9. python就业方向及工资-Python的就业的方向和前景
  10. stm32跑python-简易数据采集分析流程.stm32+python