【问题标题】:If Entity Framework / DbContext is the DAL / Repository, where does it fit within 3-tier architecture?如果 Entity Framework / DbContext 是 DAL / Repository,它在 3 层架构中的位置是什么?
【发布时间】:2013-05-27 23:44:06
【问题描述】:

我整天都在阅读 StackOverflow 和其他网站上关于最佳架构实践的文章,但其中有很多相互矛盾的想法和意见。

我终于确定了一种方法,但我很难决定在哪里放置 EF 对象(DbContext、Fluent API、播种数据等)。这是我目前拥有的:

ASP.NET MVC 项目:实际的 Web 项目。包含标准视图、控制器和视图模型(在 Models 文件夹中)。

域模型项目:包含定义数据库(域)对象的所有 POCO 类。目前,未提及或引用任何 EF 对象。

服务层项目:包含每种类型的域对象(例如,IProductService、IOrderService 等)的服务对象。每个服务都引用 DbSet 等 EF 对象并处理业务规则 - 例如,添加产品、获取产品、将产品附加到订单等。

所以问题是,在这个配置中,EF 类去哪里了?最初我认为是在服务层,但这似乎没有意义。然后我想将它们放在域模型层中,但随后它将域模型与 EF 联系起来,EF 本质上是一个 DAL / 存储库。最后,我考虑为 EF 创建一个单独的 DAL 项目,但考虑到其中可能包含 3-4 个文件(DbContext 和其他一些小文件),这似乎是一种巨大的浪费。

任何人都可以提供任何指导吗?

【问题讨论】:

  • 是什么驱使您创建三个项目,而不是一个?
  • 更好的可扩展性。使用一个单独的域模型项目和一个服务项目,您可以拥有另一个应用程序(例如,WinForms 应用程序),该应用程序可以轻松使用域和业务逻辑,而无需复制代码。此外,如果有 WinForms 应用和 MVC 应用,则只需在一处而不是两处进行业务规则更改等操作。

标签: c# asp.net .net asp.net-mvc entity-framework


【解决方案1】:

不需要域模型,因为它是冗余的。 EF 类可以直接充当域模型,并在将其发送到 View 时将其转换为 View Model。 EF 可以分成不同的类库。他们中的大多数人使用存储库模式以及任何 ORM,以防万一他们去替换会很容易。但是我看到了对使用存储库模式的批评,请查看this

【讨论】:

  • 我使用的是 EF Code First,所以我自己创建了 POCO 类。然而,我的印象是我的领域模型应该是纯粹的 POCO 类,而 EF DbContext 等人应该存在于其他地方。这是错的吗?
  • 就像 Sunny 提到的那样——获取您的 POCO 类并在您的解决方案中创建一个新项目,该项目仅包含您的 POCO 类(而不是您的 DbContext).. 该程序集可以非常轻巧并且不需要对 EF 有任何依赖 .. 您的 DbContext 将进入您的 WPF/WinForm/WebForm/MVC/Silverlight/Whatever-assembly,这将取决于 EF。这是最好的方法,也是您通常在 Microsoft 首先显示 EF 代码时所展示的方法。
  • @DerekCurtis:问题是如果我把DbContext放在MVC项目中,那么Service Layer需要引用MVC项目,而MVC项目也需要引用Service Layer。好像是循环引用?
  • 如果你想使用服务层,那么 dbcontext 相关代码将在服务中。 DAL 将包含 EF、IUow 等。 POCO 可以存在于不同命名空间下的不同库或 DAL 层中。在服务和 MVC 应用程序中引用它。但是服务层就像存储库模式,不是必需的,你可以在这里直接使用 EF,单元测试没有任何问题。检查weblogs.asp.net/scottgu/archive/2010/07/16/…
  • @Sunny:所以如果我理解正确的话,你是说有 MVC 项目、POCO 项目,仅此而已?您是说服务层不是必需的,但是让 MVC 控制器直接访问 EF 并执行直接查询不是不好的形式吗?这就是为什么我正在考虑拥有服务层项目,以便控制器可以引用将处理 EF 查询和业务规则的 IService。想法?
【解决方案2】:

这是我的工作:

数据:

  • 有一个类继承自 DbContext。
    • 它包含所有数据库集。
    • 覆盖 OnModelCreating。
    • 映射主键和关系。

实体:

  • 拥有每个 POCO 课程。
    • 每个属性都装饰有所需的数据注释。

服务:

  • 每个服务都有通用方法(GetList()、Find()、Create() 等)。

业务:

  • 从客户端调用,使用服务编排执行特定任务 UserChangePassword(这将检查是否可以执行,然后执行任务,或返回错误/未授权状态等许多其他状态,以使客户端显示有关任务。我的情况是我登录的地方。

客户端(桌面/Web/Wpf/等)。

我并不是说这是最好的方法,我只是分享对我有用的方法。

【讨论】:

    猜你喜欢
    • 2011-03-12
    • 2010-12-06
    • 1970-01-01
    • 2013-05-31
    • 2011-04-27
    • 2011-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多