EF模型优先或代码优先方法?

41

我知道这个问题以前已经被问了很多次,因为我在关于模型优缺点的主题上读了不少帖子,但我仍然不能决定哪种方法适合我。我非常新于Web编程,来自SQL DB管理员/报告撰写背景。我已决定尝试构建自己的网站,可能将来会有30-40个表。

我已经看过两种方法,我更喜欢实体模型方法,因为我喜欢设计师的简洁性,也喜欢在眼前看到整个模型,它展示了总体情况的一张快照。此外,我不是一个强大的程序员,我对它生成POCO使用DbContext生成器模板的方式印象深刻,并且做好了类之间的链接。

然而,虽然我喜欢模型优先方法,但我觉得存在一些缺点,我不确定它们是否真正的缺点,还是我对模型优先方法和代码优先方法还不够了解,因为我还是很新手。

我犹豫使用模型优先方法的原因如下:

- 主要是因为我很难找到使用MVC 3的模型优先方法的教程。我发现使用DbContext的最好的教程是Julie Lerman写的,但她没有讲解Buddy类,这在使用数据注释和进行其他更改时很重要,并且不会在重新生成POCO时丢失。大多数与MVC 3相关的教程似乎都使用了代码优先方法。大多数人说这是因为教师不想专注于EF,而是更多地展示MVC,我个人认为这是因为Microsoft正在倡导代码优先方法而非其他方法:)

- 如果创建Buddy类是一个好习惯,那么为什么我找不到很多针对MVC 3显示这些类的教程呢?Buddy类是否是View Model的另一个名称?为什么我找不到任何由Microsoft显示这些buddy / view模型在MVC 3中使用的教程?

-我试图在两个表之间建立基本的一对一关系。在模型优先中,您必须将每个表的标识键设置为相同的字段,而不是在其中一个表中使用FK,这可能会在通过1到1关系链接3个或更多表时变得有些混乱。在代码优先中,解决这个问题的方法是手动使用模型构建器进行设置。我认为在MF中,您可以通过进入XML来更改关系,但我不喜欢这样做。

-需要有关代码优先问题的更多支持/帮助

我犹豫使用Code First方法的原因是:

-我是新手程序员。

-随着项目扩展,我看到跟踪表和关系会变得非常困难。

-没有模型图,我必须说我真的很喜欢这个想法。

-通过配置类将实体映射到数据库我觉得很难 :)。

-更新表将需要更改代码和数据库。在模型优先中,只需更改模型,它将自动更新数据库和代码,不过,如果您使用buddy类,则可能还需要更新这些类。

此外,现在我看到人们在某种程度上结合了代码优先和数据库优先方法,即您不让Code First生成数据库,而是手动创建数据库并使用代码优先API到EF来访问它。

我对所有的选项和优缺点感到眼花缭乱。我只想继续创建我的网站,而不必考虑采取哪种方法。有人可以根据我说的或者他们认为将来更流行的方式来给我一些见解吗?

非常感谢Dave

4个回答

37

这个问题太长了,下次您应该将问题分成多个单独的问题。

代码优先 x 模型优先 x 数据库优先

你是一个数据库专家,所以对于你来说,最好的方法是采用增量式的数据库优先方法,其中你在DB(或VS数据库工具)中定义内容并从数据库更新你的模型。这将使你对数据库有很大的控制权,允许你逐步构建应用程序和数据库。为什么我认为你会喜欢它:

  • 你以前做过SQL DB管理员-你可能知道一些关于DB和如何为性能设计它们的知识-EF不会为你做任何事情。EF不会为您创建索引等。
  • 30-40张表意味着您不会一次性构建模型。您将从小模型开始,并持续扩展它。一旦您开始在DB中进行更改或添加初始化数据,您将不想丢失这些更改和数据。Code-first只允许删除整个数据库并从头开始重新创建。模型优先允许逐步构建数据库,但您需要Entity Designer Database Generation Power pack和VS 2010 Premium或Ultimate($5,000-$10,000)。

更多关于数据库优先、模型优先和代码优先之间的区别的内容。另一个答案描述了使用代码优先和与设计师一起工作之间的区别

DbContext API + 数据库优先 + Fluent映射

我认为这是最困难的方法。您将首先定义数据库,然后使用DbContext fluent API或数据注释来定义映射。这需要对EF及其映射背后的所有原理有很好的了解,以及对DbContext API中使用的默认约定的了解。它将为您提供良好且明确的映射控制,但是需要做最多的工作。这绝对是最困难的方法。此外,并不推荐使用它,因为DbContext API最初是为代码优先方法创建的。

DbContext API x ObjectContext API

一旦您开始使用EDMX(实体设计器),您可以选择使用DbContext Generator T4模板或POCO Generator T4模板。决定权在您手中-您可以使用DbContext API(第一个模板)或ObjectContext API(第二个模板),它有更好的文档记录,而且您还可以使用两本很棒的书:

我只知道ObjectContext API的相关内容来自于这些书籍、作者博客和实践+Reflector。

DbContext API目前没有任何相关书籍。您可以查看一些主要网站以获取相关信息:

我所知道的有关DbContext API的内容都来自这些博客和实践+Reflector。

即使您使用代码优先,仍然可以使用类图来可视化您的类图(它与EDMX不同,但足以获得大局观)。

在Stack Overflow或MSDN论坛上搜索将为您解答大多数您在使用这两个API时遇到的问题。

MVC 3

使用实体框架与MVC 3没有特别之处。用于数据验证注释的Buddy类被认为是不好的实践。Buddy类是单独的类,用作应用于实体的元数据持有者。视图模型是用于在控制器和视图之间传输数据的类。视图模型应该针对每个具体的视图具有其自己的验证注释,因为当使用相同的实体类型在应用程序的不同屏幕中工作时,通常需要不同的验证要求,例如编辑和插入屏幕。

尽管这不被视为良好的实践,但在实体中添加验证是可能的 - 你可以手动为每个实体创建 buddy 类,或者尝试修改 T4 模板直接为你生成注释(这很困难)。

一对一关系

是的,EF 只能在主键上创建一对一关系。原因是 EF 不支持唯一键/约束。没有绕过此问题的方法,使用数据库中的唯一键也无法改变它。


嗨Ladislav,感谢您的所有评论!您说得很对,我想逐步构建我的应用程序和数据库。我可能会有大量的初始数据和类型表,不想每次更改模式时都失去它们。您提到Code-first只允许删除整个数据库并从头开始重建,但我在Scott Gu的博客上看到了这篇文章,解释了可以创建数据库,然后使用Code First http://weblogs.asp.net/scottgu/archive/2010/08/03/using-ef-code-first-with-an-existing-database.aspx。 - davey
我在另一篇帖子中看到您使用了DB First方法,这个方法对您的工作有何影响?您是否遇到任何问题或限制?此外,您是否有使用View Model与DB或Model First的示例?如何将它与edmx生成的.tt文件中的部分类“连接”起来?谢谢。 - davey
@davey:在我的回答中,我在“DbContext API + Database-first + Fluent mapping”部分提到了使用现有数据库的Code First。但我不称其为Code First,因为它并不是真正的Code First。 - Ladislav Mrnka
@davey:如果你发现EF生成的查询很慢,那么数据库优先是不错的选择。你可以构建一些存储过程或视图来提高应用程序的性能。我没有使用视图模型的示例,但如果你在Stack Overflow上搜索,你会发现很多人问这个常见问题。答案更可能会提到,你需要自己编写视图模型,并使用AutoMapper在实体和视图模型之间进行映射。 - Ladislav Mrnka
很抱歉,你确实提到了这一点。你是对的,在尝试进行流畅映射时,它看起来很棘手,对于我这样的新手来说可能会非常困难。使用Automapper并创建视图模型的想法听起来需要做很多额外的工作。我喜欢CodeFirst的原因是可以在POCO中添加数据注释,而不必担心类被覆盖。我从未使用过Automapper,将会研究一下。我很难在Stack Overflow上找到任何“视图模型”的示例,虽然有很多关于它们的信息,但没有代码示例展示如何实践。谢谢。 - davey
不应该有三种方法。您应该能够从数据库或代码类更新模型,应该能够从模型更新代码,并且可以从模型更新数据库。我喜欢Model First,但似乎微软已经放弃了它,现在集中于Code First,但两者都没有完全实现。Model First中没有属性,Code First中没有视图。Database First似乎只是一种种子模型的方法,而不是一个完全独立的方法。所有这些技术和功能应该同时可用,而不是3种方法将您锁定并留下某些功能。 - Dave

8

相对来说较简单。如果您不关心数据库模型,请使用代码优先。如果您关心,请使用模型优先(或数据库优先)。这取决于您的重点所在,是数据中心还是代码中心。


2
嗨,Mystere man,我认为这不是关心数据库模型(设计)与否的问题。归根结底,所有方法都建立一个模型,不是吗?选择用代码、模型设计师或通过数据库构建模型的工具,更多的是选择什么工具来构建模型的问题,不是吗? - davey
@davey - 不完全是这样。如果你对数据库模型的设计有非常强烈的意见,你不会使用Code First,因为Code First可能无法按照你想要的方式构建模型。Code First允许您构建站点而不必考虑数据库将如何物理存储它。我无法想象任何关心数据库设计的人会以这种方式工作。 - Erik Funkenbusch

3
我已经研究了两种方法,只因为我喜欢设计师的简单性并且喜欢在面前看到整个模型,所以我更偏向于实体模型方法。此外,我不是一个强大的程序员,我对它生成POCO的方式和使用DbContext生成器模板以及所有类之间的链接印象深刻。

+

我发现通过配置类将实体映射到数据库是不可能的 :)

= 使用模型优先

如果创建伙伴类是一个好的实践,为什么我找不到许多关于MVC 3的教程来展示这一点?伙伴类是另一个称呼为视图模型吗?为什么我找不到任何由Microsoft展示这些伙伴/视图模型在MVC 3中使用的教程?

这可能是因为Code-First是新生事物。这就是为什么大多数MVC3教程都是关于Code-First的原因。模型优先是“更”古老的方法,并且可能是MVC2时期最受欢迎的解决方案。

顺便说一下:你已经知道我的观点,即你应该使用你最喜欢或最舒适的方法(就像上次你问我的时候告诉你的那样),但我只是想在这里添加一些东西 :)

评论后编辑:

看一下这些东西,我认为这些会对您的Code-First有很大帮助:

为ASP.NET MVC应用程序创建Entity Framework数据模型(1/10)

使用MvcScaffolding包对ASP.NET MVC 3项目进行脚手架搭建

++这些来自MIX11在channel9的精彩视频:
Scott Hanselman以他惯常的方式展示新功能
Steve Sanderson展示MvcScaffolding的强大功能


嘿,Dampe,我知道之前我已经问过一个简化版本的问题 :) 在阅读了一些关于这个主题的帖子并看到这里发布的3个答案后,大多数人似乎倾向于使用CodeFirst。虽然这不是我真正想听到的,但我从来没有见过任何人在Modelfirst上大力推荐CodeFirst,所以我认为我会遵循常规并选择CodeFirst。主要是因为我对此还很陌生,需要尽可能多的帮助。我不想在项目进行到一半时遇到我的模型出现问题,而找不到解决方案或任何可以求助的人,因为这种方法只被少数人使用。 - davey
如果你喜欢在学习的同时放松和享受,我非常推荐先观看Scott Hanselman。然后就由你决定了。可能会深入学习asp.net的新的10部分教程,之后再查看关于MvcScaffolding的第二个视频,这对于进行代码优先开发非常有用。 - Damb
谢谢Dampe,我这个周末会看一下那些视频。关于脚手架,我已经在MVC 3工具更新中试用了一下。添加控制器对话框现在支持完全自动化的创建、读取、更新和删除控制器操作以及相应的视图。这太棒了! - davey

0

如果您使用的是模型优先,那么您可以从任何版本的MVC中使用模型优先的示例,如果这是您关注的主要问题。MVC处理“模型”的方式在各个版本之间并没有真正的不同。当然,视图模型等方面有所改进,但老教程也应该能够满足您的需求。

我更喜欢代码优先,因为我认为数据库模型和域模型有不同的用途。数据库组织是为了提高数据库性能和大小,而不是帮助您的应用程序。拥有自己的模型使您能够专注于应用程序中的状态需求,而不受数据库的限制。

现在,您可以从模型优先转换到代码优先,但是您更可能会考虑数据库而不是按照自己的需求进行操作...尤其是如果您是新手。

以上仅为个人见解。


顺便说一句,如果你问我,模型驱动方法创建了半POCOs,因为它们具有很强的属性。 - Gregory A Beamer
嘿,格雷格,感谢您的回复。我尝试过查看旧教程,但我更喜欢从头到尾使用MVC 3的教程,可能是因为我懒得在不同版本之间跳转,查看旧版本的数据访问层和新版本的前端、视图等 :) 此外,在最新版本中,模型优先使用dbContext模板生成类,我只找到了一些关于此的教程。您提出了有关应用程序需求与数据库需求的一些有趣观点。谢谢。 - davey
MVC 3教程在已更改的部分非常有用。大多数需要比您现在更深入地了解。但是,我同意您的观点,如果您能找到完全符合您需求的MVC 3教程,那将是更好的解决方案。 :-) - Gregory A Beamer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接