代码优先与模型/数据库优先[关闭]


618

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

我试图全面了解使用EF 4.1构建数据访问层的所有方法。我正在使用Repository模式和IoC

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

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

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

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

那么这两种方法有什么区别?仅仅是关于VS2010 vs Enterprise Manager的偏爱吗?



5
@CADbloke Entity Framework 7现在是Entity Framework Core 1.0
RBT

6
对于任何其他浏览器,除非您能处理7000个长的XML文件并解决上述问题中的合并冲突,否则请先编写代码,以免使您头疼
Dan Pantry


4
给出的每个答案几乎都是“我认为” ...“基于主观意见”的绝对定义。
Lankymart

Answers:


703

我认为差异是:

代码优先

  • 之所以受欢迎,是因为铁杆程序员不喜欢任何一种设计器,并且在EDMX xml中定义映射太复杂了。
  • 完全控制代码(没有很难修改的自动生成的代码)。
  • 一般的期望是您不必理会DB。DB只是没有逻辑的存储。EF将处理创建,您不希望知道它是如何完成工作的。
  • 手动更改数据库很可能会丢失,因为您的代码定义了数据库。

数据库优先

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

模特第一

  • 如果您是设计师狂热者,恕我直言很受欢迎(=您不喜欢编写代码或SQL)。
  • 您将“绘制”模型,并让工作流生成数据库脚本,而T4模板生成POCO实体。您将失去对实体和数据库的部分控制,但是对于小型的简单项目,您将非常有生产力。
  • 如果要在POCO实体中使用其他功能,则必须T4修改模板或使用部分类。
  • 手动更改数据库很可能会丢失,因为您的模型定义了数据库。如果您安装了数据库生成电源包,则效果更好。它将允许您更新数据库架构(而不是重新创建)或更新VS中的数据库项目。

我希望在EF 4.1的情况下,还有其他一些与“代码优先”与“模型/数据库优先”相关的功能。首先在Code中使用的Fluent API并未提供EDMX的所有功能。我希望诸如存储过程映射,查询视图,定义视图等功能可以在首先使用模型/数据库时使用DbContext(但我还没有尝试过),但是首先不在代码中使用。


5
@Ladislav-谢谢您的全面答复。需要澄清的是:除了流利的API的某些限制外,这些方法之间没有真正的技术差异吗?更多关于开发/部署过程/方法的信息?例如,对于Dev / Test / Beta / Prod,我有单独的环境,由于在架构上进行更改可能需要进行一些复杂的数据修改,因此我将在Beta / Prod上手动升级数据库。使用Dev / Test,我很高兴EF删除并创建数据库,因为我将自己在初始化程序中将测试数据植入它们中。
2011年

152
我已经设计数据库很久了,我似乎无法想象除了数据库之外首先要做任何事情。实际上,我仍然为更高容量的select语句等编写了很多存储过程,然后我以性能为名将函数导入EF模型。
史蒂夫·沃瑟姆

9
大量选择语句是什么意思?存储过程并不比SELECT从应用程序发送更快。
皮奥特(霹雳)霹雳州2012年

20
可以在应用程序中使用SQL。该SQL很可能会嵌入到已编译的代码中,并且任何更改都需要重新编译和重新部署,而存储过程更改仅需要编辑存储过程。在这种情况下,客户/客户/用户受更改的影响较小。
CodeWarrior 2012年

5
@JakubKonecki,无论您DbContextObjectContext简单使用中存在的什么都找不到((IObjectContextAdapter)dbcontext).ObjectContext
Shimmy Weitzhandler 2012年

134

我认为“编程实体框架”作者朱莉·莱尔曼(Julie Lerman)的这个简单的“决策树”应该有助于更加自信地做出决策:

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

更多信息在这里


111
这还不完整。如果您不想使用视觉设计器,但拥有一个现有数据库怎么办?
Dave New

14
更糟糕的是...现实生活中的决策不是由图表决定的,而是由您在使用代码优先时遇到的技术限制来完成的,例如,您无法在字段上创建唯一索引,或者无法为此删除树表中的层次结构数据。需要使用context.Table.SqlQuery(“ select ...”)进行CTE。模型/数据库首先没有这些缺点。
伊丽莎白2013年

32
@davenewza是第一个路径,不是吗?
克里斯S

3
@davenewza现有数据库=>现有类?代码优先:数据库优先:)
riadh gomri

4
@davenewza使用实体框架Powertools从数据库创建POCO类。代码优先到现有数据库
Iman Mahmoudinasab 2014年

50

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

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

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

代码优先的优势是非常干净和简单的代码。您可以完全控制此代码,并且可以轻松地对其进行修改并将其用作视图模型。

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


7
如果要使用SQL脚本手动更新生产环境,则仍可以使用Code First进行相同的操作。您只需根据需要生成更改脚本。有几种工具可以使这些增量自动化,并且您可以继续使用Code First。您只需要简单地将Code First初始化程序更改为CreateDatabaseIfNotExists之类的内容,以免删除当前数据库。
Esteban Brenes

某些区别是先导入视图,然后在视图成为表的地方重新生成数据库。很难生成新的数据库并与产品数据库进行比较以查看是否同步。
戴夫

Model First不支持用户定义的SQL函数(至少在EF4中,不知道它是否已更改)。使用Database First,您可以导入UDF并在LINQ查询中使用它们。
Tsahi Asher 2014年

没有区别吗 尝试导入视图和SimpleMembership表,然后根据模型生成数据库,然后看看您得到了什么。差远了!这些应该往返,但是MSFT基本上已经放弃了MF和DF来代替CF,这在使用视图和存储过程方面也不完整。
戴夫

您可以禁用基于代码的第一批迁移的数据库重新创建过程,并在模型和数据库中手动进行。您可以通过在web / app.config中的<EntityFramework> ..... <contexts> <context type =“ myNamespace.mydbContext”,“ myassemblyORProject”,“ myassemblyORProject” disableDatabaseInitialization =“ true” />中指定disableDatabaseInitialization =“ true”来实现</ EntityFramework>您可以删除迁移文件夹。
Hasteq

37

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

在Entity Framework中使用代码优先设计的3个理由

1)减少工作量,减少膨胀

使用现有数据库生成.edmx模型文件和关联的代码模型会导致大量自动生成的代码。恳请您不要触摸这些生成的文件,以免破坏某些内容,否则下一代的更改将被覆盖。上下文和初始化程序也卡在了这个烂摊子中。当需要向生成的模型添加功能时,例如计算的只读属性,您需要扩展模型类。最终这几乎是每个模型的要求,并且最终您扩展了所有模型。

首先使用代码,您的手工编码模型将成为您的数据库。您正在构建的确切文件将生成数据库设计。如果要添加属性或数据库不需要知道的其他任何内容,则没有其他文件,也不需要创建类扩展。只要遵循正确的语法,就可以将它们添加到同一类中。哎呀,如果需要的话,您甚至可以生成一个Model.edmx文件来可视化您的代码。

2)更好的控制

当您第一次进入DB时,您将无法为模型生成供应用程序使用的模型。有时,命名约定是不可取的。有时,关系和关联并不是您想要的。有时,与延迟加载的非暂时性关系会严重破坏API响应。

尽管几乎总是存在您可能会遇到的模型生成问题的解决方案,但是先执行代码可以让您从一开始就进行完整而精细的控制。您可以从舒适的业务对象中控制代码模型和数据库设计的各个方面。您可以精确指定关系,约束和关联。您可以同时设置属性字符限制和数据库列大小。您可以指定要加载的相关集合,或者根本不序列化。简而言之,您需要负责更多的工作,但是您可以完全控制应用程序的设计。

3)数据库版本控制

这是一个很大的。对数据库进行版本控制很困难,但是通过代码优先和代码优先的迁移,它更有效。由于数据库架构完全基于代码模型,因此通过控制源代码的版本,您正在帮助对数据库进行版本控制。您负责控制上下文初始化,这可以帮助您执行诸如种子固定业务数据之类的事情。您还负责创建代码优先迁移。

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


31

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

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

  • 简单的属性修饰 -您可以使用验证,需求等修饰字段。属性,对于EF建模来说很尴尬
  • 没有奇怪的建模错误 -EF建模经常有奇怪的错误,例如,当您尝试重命名关联属性时,它需要与基础元数据匹配-非常不灵活。
  • 不难合并 -使用诸如Mercurial之类的代码版本控制工具时,合并.edmx文件很麻烦。您是曾经使用过C#的程序员,并且您正在那里合并.edmx。代码优先的情况并非如此。
  • 首先对比一下Code,您将拥有完全的控制权,而无需处理所有隐藏的复杂性和未知数。
  • 我建议您使用“程序包管理器”命令行工具,甚至不要使用图形工具将新的控制器添加到支架视图中。
  • DB迁移 -然后,您也可以启用迁移。这是如此强大。您在代码中更改了模型,然后框架可以跟踪架构更改,因此您可以无缝部署升级,并自动升级架构版本(并在需要时降级)。(不确定,但这也可能适用于模型优先)

更新资料

该问题还要求将代码优先与EDMX模型/数据库优先进行比较。代码优先也可以用于这两种方法:


3
“模型优先”不是首先编码POCO,而是“代码优先”,“模型优先”是Visual Designer,用于自动生成POCO,然后从模型生成数据库。
迭戈·门德斯

如今,无论是可视化路线还是代码路线,您都可以先执行“模型”或“数据库”。第一个是手动设计(通过代码或可视化编辑器),第二个是构建数据库并创建模型(POCO或EDMX)。
托德

11

我首先使用EF数据库,以便提供更大的灵活性并控制数据库配置。

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

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

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


4
可以定义使用代码第一组合键- stackoverflow.com/questions/5466374/...
的Jakub Konecki

3
对于将来的读者而言,情况已不再如此,您可以在EF Code First中添加索引,多列主键以及此类内容。
tobiak777

1
EF应该固定下来,以便所有3种方法都可以在同一数据库上互换使用,因为这3种方法都有优点和缺点
Dave

另外,由于将来会迁移到其他IDE /语言,并且我希望拥有牢固的集成数据库结构,因此我会首先使用数据库,这不是理想的代码优先解决方案的事实,我更喜欢数据库的另一个事实是可以灵活地更改数据库的任何部分数据存储。
QMaster

7

在SP1之前,使用大型模型的工作非常缓慢(在SP1之后还没有尝试过,但是现在说来这很短)。

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

当您使用源代码控制系统时,您可以轻松地跟踪POCO的历史记录,而使用设计人员生成的代码并不是那么容易。

我有POCO基地,这使很多事情变得很容易。

我有所有表的视图,每个基本视图都为我的外键带来了基本信息,而我的视图POCO是从POCO类派生的,这再次非常有用。

最后,我不喜欢设计师。


8
“当您使用源代码控制系统时,您可以轻松地跟踪POCO的历史记录,而使用设计人员生成的代码并不是那么容易。” -我将设计师生成的代码保留在源代码管理中,因此我始终可以查看历史记录。
2011年

1
@JakubKonecki您是否曾经尝试在3人以上的团队中合并EDMX文件?这真是一种痛苦……相反,人们尝试避免合并,而只是采用另一个修订并重复自己的更改,因为合并很容易在具有数千行XML的自动生成的文件中失败。
bytecode77

6

数据库优先方法示例:

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

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


您能否详细说明采用数据库优先的方法可以减少数据丢失?如果要将现有表一分为二,将如何执行数据转换?
Jakub Konecki 2012年

您可能最终会编写一个负责转换的sql脚本。通常,MS宣布使用其新版本来改进Code First数据迁移,因此在将来可能不会成为争论。
ckonig 2012年

首先,数据库的问题是数据库设计通常具有错误的抽象,这些抽象会泄漏到您的模型...联结表等中。数据库的工作仅仅是保留模型。
Nerdfest 2014年

这个“答案”是一种观点,对您的论点毫无根据,一个句子也没有立场。
TravisO '17

您能否详细说明采用数据库优先的方法可以减少数据丢失?
amal50

4

恕我直言,我认为所有模型都占有很大的位置,但是模型优先方法存在的问题是在许多大型企业中,DBA控制数据库,如果不使用数据库优先方法就无法灵活地构建应用程序。我参与过许多项目,在部署时,他们需要完全控制。

因此,尽管我同意所有可能的变体,例如代码优先,模型优先,数据库优先,您必须考虑实际的生产环境。因此,如果您的系统将是一个具有许多用户的大型用户基础应用程序,并且DBA正在运行该节目,那么您可能会认为数据库优先是我的唯一选择。


你是对的。MS给程序员提供了不同的方法,因为实际情况是不同的。您应该了解所有情况,并根据自己的情况决定最适合该项目的项目,然后再选择最喜欢的项目。
斯特林·迪亚兹

0

我认为代码的优势之一是可以备份对Git等版本控制系统所做的所有更改。因为您所有的表和关系都存储在本质上只是类中,所以您可以回到过去,看看以前的数据库结构是什么。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.