8

我正在为我的应用程序使用实体框架4.1和ASP.Net MVC 3。 MVC提供了表示层,一个中间库提供了业务逻辑和实体框架类的行为作为我猜想的数据层?实体框架,应用程序层和关注点分离

我可以将实体框架代码分成一组存储库类或其适当的变体,无论构成一个有价值的数据层,但是我在解决设计问题时遇到了问题。

如果存在多层方法来帮助我关注问题,那么我认为我选择的数据持久性也不应该成为表示层的问题。问题是,通过使用实体框架,我基本上紧密地将我的应用程序与实体更改自动跟踪并保持的概念紧密耦合。

因此,让我们假设在一个假设的世界中,我找到了一个不使用实体框架的理由,并希望将其交换出去。一个设计良好的解决方案应该允许我在适当的层执行此操作,而不会影响依赖层,但是因为所有代码都是在知道数据层跟踪对象更改的情况下编写的,所以我只能将实体以类似的方式工作的框架,例如nHibernate。

如何使用实体框架但不需要以假定实体更改正在被数据层跟踪的方式编写我的代码?

更新那些仍然不知道这个问题在他们自己的情况:
Ayende Rahien写了一大篇击落这整个论点: http://ayende.com/blog/4567/the-false-myth-of-encapsulating-data-access-in-the-dal

回答

9

如果你想继续这种方式,你应该放弃的编程工作,去学习哲学。实体框架是对持久性的抽象,并且存在一条规则Leaky abstraction,其规定任何不平凡的抽象在某种程度上是泄漏的。

敏捷方法带有一个非常有趣的现象:不要为假设情况做准备。大部分时间只是Gold plating。每个变化都有其成本。在项目后期更改持久层代价很高,但也非常少见。从客户角度来看,没有理由在大多数不需要此项变更的项目中支付部分成本。如果我们更深入地讨论客户的观点,我们可以说他不应该为此付出代价,因为选择后来必须替换的糟糕API是开发人员/架构师的失败。定期重构您的代码,但仅限于添加客户需要的新功能所需的点,否则您很难在市场上具有竞争力。这当然有一些例外:

  • 客户希望(或架构要求它出于任何原因,客户同意)这样的抽象。在这种情况下,您必须指望它,并为此类更改定义架构。
  • 它是爱好或开源项目在这里你可以做你想做的,因为它不是由某些资源

现在你的问题的制约。如果你想要这样高层次的抽象,你不应该将实体暴露给你的控制器。从业务层(甚至是存储库)公开DTO,并向这些DTO添加IsNew,IsModified,IsDeleted等字段。现在您的用户界面与持久性完全分离,但您的架构要复杂得多,并且可能没有理由产生这种复杂性 - 它已经过时了。另一种方法可以简单地关闭跟踪(为每个查询添加AsNoTracking())并在您的实体上创建代理(context.Configuration.ProxyCreationEnabled) - 延迟加载也不会起作用。这就像扔掉大部分功能持久性框架提供给你的。

还有其他观点。我建议您阅读Ayende's最近关于存储库和他对夏普体系结构的评论。

+1

只是想补充一点,所有的ORM也会分担一些难以替换的差异。 关闭我头脑中的差异包括级联删除行为,急切的加载行为,linq行为(必须在跳过之前执行命令),存储过程/视图行为,临时sql行为,投影行为,甚至与LINQ。神话可交换的ORM层不存在。无论如何,你需要做很多工作。 – jfar 2011-05-11 21:10:04

+0

很好的答案!老实说,有时候我只是需要将这些东西从别人身上反弹出来,让我放心。 – 2011-05-12 10:26:53

+0

对于单个应用程序来说,这是一个很好的观点,但是如果您计划编写多个应用程序并且它们都应该使用相同的基本概念(也许还有代码库),那该怎么办?然后事情变得复杂,你不能只是“建立客户想要的”(他不知道)。 – Marc 2017-07-06 11:40:18

0

你应该实现,如果你的仓库模式和普通POCOS担心可能会更换EF。

在Codeplex上有一个很好的项目,它覆盖了域驱动设计,包括文档。看看那个。

http://microsoftnlayerapp.codeplex.com/

+0

在我看来,这是击败持久性无知的目的。我的控制器层不应该关心我是使用ORM还是存储库模型。 – 2011-05-11 18:53:15

+0

如果这两件事不提供相同的功能,那么你的控制器层肯定应该关心。某些自动跟踪和保持更改需要根本不同的控制器逻辑。 – Tridus 2011-05-11 21:37:29

+0

你是对的,正如我所说的,你可以使用普通的POCOS并将它们作为DTO传递 - 它们应该是持续的无知。存储库模式不会让鸽子使用任何特定的数据访问方法。 – 2011-05-13 00:14:44

2

简答题?你没有。您可以关闭EF的跟踪,然后不用担心,但就是这样。

如果您打算编写您的表示层,并期望自动跟踪并保持更改,那么无论您替换EF都必须这样做。您不能将它交换出来,因为它不会自动跟踪并保持更改,只是希望事情能够继续工作。这就像一个依赖TCP/IP连接进行双工通信的系统,将它交换到一个HTTP连接(HTTP的本质并不是真正的双工),并希望事物以同样的方式工作。它没有。

如果您希望能够将持久层换成别的东西而不必更改其他任何东西,那么您需要在自己的自定义代码中包装EF(或其他),以提供所需的功能。那么你必须提供任何不是由你交换的东西提供的实现。

这是可行的,但对于实际上很少发生的问题,这将是一项可怕的工作。这也会增加项目的复杂性。拉迪斯拉夫喋喋不休:这不值得抽象。

0

请在阅读微软n层项目之后,阅读ayenede's weblog. Mr.ayende发布了关于微软n层项目优势和劣势的系列文章。

相关问题