c# - DTO 加上 UnitOfWork 模式是为 Web 应用程序设计 DAL 的好方法吗?

标签 c# design-patterns entity-framework-4 data-access-layer .net-4.0

我正在使用 Entity Framework 实现 DAL。在我们的应用程序中,我们有三层(DAL、业务层和表示层)。这是一个网络应用程序。当我们开始实现 DAL 时,我们的团队认为 DAL 应该有一些类,其方法接收业务层服务提供的 ObjectContext 并对其进行操作。该决定背后的基本原理是不同的 ObjectContext 看到不同的数据库状态,因此某些操作可能会由于外键匹配问题和其他不一致问题而被拒绝。

我们注意到,从服务层生成和传播对象上下文会在层之间产生高耦合。因此我们决定使用 Automapper 映射的 DTO(不是非托管实体或自跟踪实体争论高耦合,将实体暴露给上层和低效率)和 UnitOfWork。所以,这是我的问题:

  1. 这是设计网络应用程序 DAL 的正确方法吗?为什么?
  2. 如果您对 1. 的回答是"is",那么如何协调 DTO 的概念与 UnitOfWork 模式?
  3. 如果您对 1. 的回答是“否”,那么哪种方法是为 Web 应用程序设计 DAL 的正确方法?

如果可能,请提供支持您答案的引用书目。

关于目前的设计:

该应用程序计划在三个层次上开发:Presentation、Business 和 DAL。业务层既有门面又有服务

有一个名为 ITransaction 的接口(interface)(只有处理和保存更改的两种方法)仅在服务中可见。为了管理事务,有一个类 Transaction 扩展了 ObjectContext 和 ITransaction。我们设计这个时考虑到在业务层我们不希望其他 ObjectContext 方法可访问。

在 DAL 上,我们使用两种通用类型(一种用于实体,另一种用于其关联的 DTO)创建了一个抽象存储库。该存储库具有以通​​用方式实现的 CRUD 方法和两个通用方法,用于使用 AutoMapper 映射通用存储库的 DTO 和实体。抽象存储库构造函数将 ITransaction 作为参数,它希望 ITransaction 是一个 ObjectContext,以便将其分配给其 protected ObjectContext 属性。

具体的存储库应该只接收和返回 .net 类型和 DTO。

我们现在面临这个问题:创建的通用方法不会为附加实体生成临时或持久 ID(直到我们使用 SaveChanges(),因此破坏了我们想要的事务性) ;这意味着服务方法不能使用它来关联 BL 中的 DTO)

最佳答案

这里发生了很多事情...我假设您使用的是 3 层架构。也就是说,我不清楚您做出的一些设计决定以及做出这些决定背后的动机是什么。一般来说,我会说你的 ObjectContext 不应该在你的类中传递。应该有某种管理器或存储库类来处理连接管理。这解决了您的数据库状态管理问题。我发现 Repository 模式在这里非常有效。从那里,您应该能够相当容易地实现工作单元模式,因为您的连接管理将在一个地方处理。鉴于我对您的架构的了解,我会说您应该使用 POCO 策略。使用 POCO 不会将您与任何 ORM 提供程序紧密耦合。优点是您的 POCO 将能够与您的 ObjectContext 交互(可能通过某种类型的存储库),这将使您能够看到更改跟踪。同样,从那里您将能够实现工作单元(事务)模式,使您能够完全控制业务事务的行为方式。我发现这是一篇非常有用的文章,可以解释所有这些是如何组合在一起的。该代码有问题,但准确说明了您所描述的架构类型的最佳实践:Repository, Specification and Unit of Work Implementation

我对问题 1 的简短回答是“否”。上面的链接提供了我认为对您来说更好的方法。

关于c# - DTO 加上 UnitOfWork 模式是为 Web 应用程序设计 DAL 的好方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4554966/

相关文章:

c# - 请解释为什么这个 c# 扩展方法有效

c# - 多边形三角剖分 c#

c# - Entity Framework 加入 3 个表

c# - mvc 中的 ON DUPLICATE KEY UPDATE 问题

c# - 即使使用任务,Blazor UI 也会卡住

java - 在 Java 中用原语规避代码膨胀的模式

java - Java 中的泛型方法模式

java - 克隆(通过 Cloneable 接口(interface)或复制构造函数)对象与在原型(prototype)模式中创建新对象的性能

c# - Entity Framework 4.0 如何确定实体的工厂方法需要哪些参数?

c# - Entity Framework - 为导航属性指定继承类型的查询