代码优先与模型/数据库优先

Jak*_*cki 607 entity-framework poco ef-code-first entity-framework-4.1 ef-database-first

使用实体框架4.1代码优先于模型/数据库优先使用EDMX图表有什么优缺点?

我正在尝试完全理解使用EF 4.1构建数据访问层的所有方法.我正在使用Repository模式和IoC.

我知道我可以使用代码优先方法:手动定义我的实体和上下文并用于ModelBuilder微调模式.

我还可以创建一个EDMX图表并选择一个代码生成步骤,该步骤使用T4模板生成相同的POCO类.

在这两种情况下,我最终POCO都得到了ORM不可知的对象和源自的上下文DbContext.

数据库优先似乎最吸引人,因为我可以在企业管理器中设计数据库,快速同步模型并使用设计器对其进行微调.

那么这两种方法有什么区别?是仅仅关于VS2010与企业管理器的偏好?

Lad*_*nka 690

我认为差异是:

代码优先

  • 非常受欢迎,因为硬核程序员不喜欢任何类型的设计师,并且在EDMX xml中定义映射太复杂了.
  • 完全控制代码(没有自动生成的代码很难修改).
  • 一般的期望是你不用担心DB.DB只是一个没有逻辑的存储.EF将处理创建,您不想知道它是如何完成工作的.
  • 由于您的代码定义了数据库,因此很可能会丢失对数据库的手动更改.

数据库第一

  • 如果您拥有由DBA设计的数据库,单独开发或者如果您有现有数据库,则非常受欢迎.
  • 您将让EF为您创建实体,在修改映射后,您将生成POCO实体.
  • 如果您想要POCO实体中的其他功能,您必须T4修改模板或使用部分类.
  • 可以手动更改数据库,因为数据库定义了您的域模型.您始终可以从数据库更新模型(此功能非常有效).
  • 我经常在VS数据库项目中使用它(仅限Premium和Ultimate版本).

模型第一

  • 恕我直言,如果你是设计师粉丝(=你不喜欢编写代码或SQL).
  • 您将"绘制"模型,让工作流生成数据库脚本,T4模板生成POCO实体.您将失去对实体和数据库的部分控制权,但对于小型简易项目,您将非常高效.
  • 如果您想要POCO实体中的其他功能,您必须T4修改模板或使用部分类.
  • 由于模型定义了数据库,因此很可能会丢失对数据库的手动更改.如果安装了数据库生成电源组,则效果会更好.它将允许您更新数据库模式(而不是重新创建)或更新VS中的数据库项目.

我希望在EF 4.1的情况下,首先还有一些与Code First与Model/Database相关的其他功能.Code中使用的Fluent API不提供EDMX的所有功能.我希望存储过程映射,查询视图,定义视图等功能首先使用模型/数据库时工作DbContext(我还没有尝试过),但它们不在Code中.

  • 我一直在设计数据库这么久我似乎无法想象除了数据库之外还做任何事情.事实上,我仍然为更高容量的select语句编写了很多存储过程,然后我将以性能的名义将函数导入到EF模型中. (151认同)
  • 您*可以*在您的应用程序中使用SQL.SQL很可能嵌入在已编译的代码中,任何更改都需要重新编译和重新部署,而存储过程更改只需要编辑存储过程.客户/客户/用户受此情况变化的影响较小. (20认同)
  • 高容量选择语句是什么意思?存储过程并不比SELECTs从应用程序发送的速度快. (9认同)
  • @Ladislav - 谢谢你的全面答复.只是为了澄清:除了流畅的API的某些限制之外,这些方法之间没有真正的*技术*差异吗?它更多的是关于开发/部署过程/方法?例如,我有Dev/Test/Beta/Prod的单独环境,我将在Beta/Prod上手动升级数据库,因为对模式的更改可能需要一些复杂的数据修改.使用Dev/Test我很高兴EF可以删除和创建数据库,因为我将在初始化程序中自己为测试数据提供种子. (5认同)
  • @JakubKonecki,无论你在`ObjectContext`中存在的'DbContext`中找不到,只需使用`((IObjectContextAdapter)dbcontext).ObjectContext`. (5认同)
  • @Jakub:没有区别.这些只是使用相同EF核心的不同方法.这就像在配置中,通过属性或使用流畅的API配置IoC - 仍然是相同的结果,但在每种使用的方法中有不同的方法和一些限制.检查这个问题:http://stackoverflow.com/questions/5433318/how-do-i-allow-the-ef4-codefirst-database-initializer-to-run-under-development-b有一些好主意如何解决不同环境的问题. (3认同)
  • @Peri,虽然存储过程并不比select语句快,但你可以控制DML与使用ORM,你可以使用生成的内容.在许多情况下,ORM生成的sql与dba手工创建的内容相比几乎没有其他性能...... (3认同)
  • 好的我同意ORM,但你可以在你的应用程序而不是SP中使用SQL. (2认同)
  • 根据我的经验,如果您使用的是旧版本的SQL Server,则可以先使用代码.就像我的情况一样,我目前正在使用SQL Server 2003,这就是我使用代码优先方法的原因.原因:数据库优先和模型优先方法支持SQL Server 2005及更高版本.虽然,您可以将它与SQL 2003一起使用,但配置它需要花费大量时间.只需2美分. (2认同)

小智 129

我认为"编程实体框架"的作者Julie Lerman的这个简单的"决策树"应该有助于更有信心地做出决定:

帮助用EF选择不同方法的决策树

更多信息在这里.

  • 这还不完整.如果您不想使用视觉设计师但是您有现有数据库怎么办? (108认同)
  • @davenewza那是第一条路不是吗? (32认同)
  • 更糟糕的是......现实生活决策不是通过图表而是通过使用代码优先时遇到的技术限制来完成的,例如,您无法在字段上创建唯一索引,或者您无法在树表中删除分层数据需要使用context.Table.SqlQuery("select ...")进行CTE.模型/数据库首先没有这些缺点. (13认同)
  • @davenewza使用Entity框架Powertools从DB创建POCO类.[现有数据库的代码](http://msdn.microsoft.com/en-us/data/jj200620) (4认同)
  • @davenewza现有数据库=>现有类?代码优先:数据库第一:) (3认同)
  • 这个图是完全错误的.如果您不喜欢Visual Designer但已经有数据库怎么办? (2认同)

小智 51

数据库优先和模型优先没有实际差异.生成的代码是相同的,您可以组合这些方法.例如,您可以使用designer创建数据库,而不是使用sql脚本更改数据库并更新模型.

首次使用代码时,如果没有重新创建数据库并丢失所有数据,则无法更改模型.恕我直言,这个限制是非常严格的,不允许在生产中首先使用代码.目前它还没有真正实用.

代码的第二个小缺点是模型构建器需要master数据库的特权.如果您使用SQL Server Compact数据库或控制数据库服务器,这不会影响您.

代码优势首先是非常简洁和简单的代码.您可以完全控制此代码,并可以轻松修改并将其用作视图模型.

当您创建简单的独立应用程序而不进行版本控制并在需要在生产中进行修改的项目中首先使用model\database时,我可以建议使用代码优先方法.

  • 如果您要使用SQL脚本手动更新生产环境,您仍然可以使用Code First执行相同的操作.您只需根据需要生成更改脚本.有几个工具可以自动化这些增量,您可以继续使用Code First.您只需要将Code First初始化程序更改为CreateDatabaseIfNotExists,以便不删除当前数据库. (7认同)
  • “当您首先使用代码时,您无法在不重新创建数据库并丢失所有数据的情况下更改模型。” - 我创建了一个非常简单的 EF 代码优先项目,创建了一个迁移以将列添加到现有表中,并使用“更新数据库”应用了迁移。所有现有数据仍然存在于我的表中,所以这个说法似乎不正确? (3认同)

Jah*_*han 36

http://www.itworld.com/development/405005/3-reasons-use-code-first-design-entity-framework引用相关部分

使用代码优先设计实体框架的3个理由

1)减少臃肿,减少膨胀

使用现有数据库生成.edmx模型文件和相关的代码模型会产生大量自动生成的代码.你恳求永远不要触摸这些生成的文件,以免你破坏某些东西,或者你的更改会被下一代覆盖.上下文和初始化程序也在这个混乱中被卡在一起.当您需要向生成的模型添加功能时,例如计算的只读属性,您需要扩展模型类.这最终成为几乎所有模型的要求,并最终为所有内容提供扩展.

使用代码,您的手动编码模型将成为您的数据库.您正在构建的确切文件是生成数据库设计的原因.没有其他文件,当您想要添加属性或数据库不需要了解的任何其他内容时,无需创建类扩展.只要遵循正确的语法,您就可以将它们添加到同一个类中.哎呀,如果需要,您甚至可以生成一个Model.edmx文件来显示您的代码.

2)更好的控制

当您首先使用数据库时,您将受到为您的应用程序使用的模型生成的内容的摆布.偶尔命名约定是不合需要的.有时,关系和联想并不是你想要的.其他时候,与延迟加载的非瞬态关系会对您的API响应造成严重破坏.

虽然几乎总有一个解决方案可能会遇到模型生成问题,但是代码首先会为您提供完整且细粒度的控制.您可以在舒适的业务对象中控制代码模型和数据库设计的各个方面.您可以精确指定关系,约束和关联.您可以同时设置属性字符限制和数据库列大小.您可以指定要急切加载哪些相关集合,或者根本不进行序列化.简而言之,您负责更多的东西,但您可以完全控制您的应用程序设计.

3)数据库版本控制

这是一个很大的问题.版本控制数据库很难,但是代码优先和代码优先迁移,它更有效.因为您的数据库模式完全基于您的代码模型,所以通过控制源代码的版本,您可以帮助对数据库进行版本控制.您负责控制上下文初始化,这可以帮助您执行诸如播种固定业务数据之类的操作.您还负责创建代码首次迁移.

首次启用迁移时,将生成配置类和初始迁移.初始迁移是您当前的架构或基准v1.0.从那时起,您将添加时间戳并带有描述符标记的迁移,以帮助排序版本.从包管理器调用add-migration时,将生成一个新的迁移文件,其中包含在UP()和DOWN()函数中自动更改代码模型中的所有内容.UP函数将更改应用于数据库,DOWN函数在要回滚的事件中删除相同的更改.此外,您还可以编辑这些迁移文件以添加其他更改,例如新视图,索引,存储过程以及其他任何更改.它们将成为数据库模式的真正版本控制系统.


Tod*_*odd 30

代码优先似乎是后起之秀.我快速浏览了Ruby on Rails,它们的标准是代码优先,具有数据库迁移.

如果您正在构建MVC3应用程序,我相信Code首先具有以下优势:

  • 简单的属性修饰 - 您可以使用验证,要求等属性来装饰字段,这对于EF建模来说非常尴尬
  • 没有奇怪的建模错误 - EF建模通常会出现奇怪的错误,例如当您尝试重命名关联属性时,它需要匹配底层的元数据 - 非常不灵活.
  • 合并并不尴尬 - 当使用像mercurial这样的代码版本控制工具时,合并.edmx文件是一件痛苦的事.你是一个习惯于C#的程序员,你正在合并一个.edmx.代码优先不是这样.
  • 首先对比代码,你可以完全控制,而不需要处理所有隐藏的复杂性和未知数.
  • 我建议您使用Package Manager命令行工具,甚至不使用图形工具向scaffold视图添加新控制器.
  • 数据库迁移 - 然后您还可以启用迁移.这太强大了.您可以在代码中更改模型,然后框架可以跟踪架构更改,因此您可以无缝地部署升级,并自动升级架构版本(如果需要,可以降级).(不确定,但这可能也适用于模型优先)

更新

该问题还要求将代码优先与EDMX模型/ db-first进行比较.代码优先也可以用于这两种方法:

  • Model-first不首先编码POCO,这是Code First,Model-First是一个自动生成POCO的可视化设计器,然后从模型生成数据库. (3认同)

use*_*371 11

我首先使用EF数据库,以便提供更多的灵活性和对数据库配置的控制.

EF代码优先和模型首先看起来很酷,并提供数据库独立性,但是在这样做时它不允许您指定我认为非常基本和常见的数据库配置信息.例如,表索引,安全元数据或具有包含多个列的主键.我发现我想使用这些和其他常见的数据库功能,因此无论如何都必须直接进行一些数据库配置.

我发现在DB中首先生成的默认POCO类非常干净,但缺少非常有用的数据注释属性或映射到存储过程.我使用T4模板来克服其中一些限制.T4模板非常棒,特别是与您自己的元数据和部分类结合使用时.

模型首先似乎有很大的潜力,但在复杂的数据库模式重构过程中给了我很多错误.不知道为什么.

  • 您可以*首先使用代码定义复合键 - http://stackoverflow.com/questions/5466374/composite-key-with-ef-4-1-code-first (4认同)
  • 对于将来的读者而言,情况已不再如此,您可以在EF Code First中添加索引,多列主键以及此类内容。 (2认同)

haz*_*nli 6

在SP1之前使用大型模型的速度非常慢,(在SP1之后没有尝试过,但据说现在很容易).

我仍然首先设计我的表,然后内部构建的工具为我生成POCO,因此它需要为每个poco对象执行重复任务的负担.

当您使用源代码控制系统时,您可以轻松地跟踪POCO的历史记录,使用设计器生成的代码并不容易.

我有一个POCO的基础,这使得很多事情变得非常简单.

我有所有表的视图,每个基本视图为我的外键提供基本信息,我的视图POCO来自我的POCO类,这非常有用.

最后我不喜欢设计师.

  • "当您使用源代码控制系统时,您可以轻松地跟踪POCO的历史记录,使用设计器生成的代码并不容易." - 我在Source Control中保留了设计器生成的代码,因此我始终可以查看历史记录. (8认同)

小智 5

数据库优先方法示例:

无需编写任何代码: ASP.NET MVC / MVC3数据库优先方法/数据库优先

而且我认为它比其他方法更好,因为这种方法减少了数据丢失。


小智 5

恕我直言,我认为所有模型都有一个很好的地方,但我对模型优先方法的问题是在许多大型企业中,DBA 控制数据库,如果不使用数据库优先方法,您将无法获得构建应用程序的灵活性。我参与了许多项目,在部署方面他们想要完全控制。

因此,尽管我同意所有可能的变化代码优先、模型优先、数据库优先,但您必须考虑实际的生产环境。因此,如果您的系统将成为具有许多用户和 DBA 运行该节目的大型用户群应用程序,那么您可能会考虑数据库第一选项,这只是我的意见。