c# - 在 DDD 中管理持久性

标签 c# .net architecture domain-driven-design persistence

假设我想创建一个博客应用程序,其中包含这两个与 EF Code First 或 NHibernate 一起使用并从存储库层返回的简单持久性类:

public class PostPersistence
{
   public int Id { get; set; }
   public string Text { get; set; }
   public IList<LikePersistence> Likes { get; set; }
}

public class LikePersistence
{
    public int Id { get; set; }
    //... some other properties
}

我想不出一个干净的方法来将我的持久性模型映射到领域模型。我想要我的 Post域模型接口(interface)看起来像这样:

public interface IPost
{
   int Id { get; }
   string Text { get; set; }
   public IEnumerable<ILike> Likes { get; }
   void Like();
}

现在下面的实现会是什么样子?也许是这样的:

public class Post : IPost
{
   private readonly PostPersistence _postPersistence;
   private readonly INotificationService _notificationService;

   public int Id 
   { 
       get { return _postPersistence.Id }
   }

   public string Text 
   { 
       get { return _postPersistence.Text; }
       set { _postPersistence.Text = value; }
   }

   public IEnumerable<ILike> Likes
   {
       //this seems really out of place
       return _postPersistence.Likes.Select(likePersistence => new Like(likePersistence ));
   }

   public Post(PostPersistence postPersistence, INotificationService notificationService)
   {
       _postPersistence = postPersistence;
       _notificationService = notificationService;
   }

   public void Like()
   {
       _postPersistence.Likes.Add(new LikePersistence());
       _notificationService.NotifyPostLiked(Id);
   }
}

我花了一些时间阅读有关 DDD 的内容,但大多数示例都是理论性的,或者在领域层中使用了相同的 ORM 类。我的解决方案看起来真的很丑陋,因为实际上域模型只是 ORM 类的包装器,它似乎不是以域为中心的方法。也顺便IEnumerable<ILike> Likes实现困扰我,因为它不会受益于 LINQ to SQL。还有哪些其他(具体!)选项可以创建具有更透明持久性实现的域对象?

最佳答案

DDD 中持久化的目标之一是 persistence ignorance这就是你似乎在某种程度上努力的目标。我在您的代码示例中看到的问题之一是您的实体实现了接口(interface)并引用了存储库和服务。在 DDD 中,实体不应该实现只是自身抽象并且对存储库或服务具有实例依赖性的接口(interface)。如果实体上的特定行为需要服务,则将该服务直接传递给相应的方法。否则,所有与服务和存储库的交互都应该在实体之外进行;通常在应用程序服务中。应用程序服务在存储库和服务之间进行编排,以调用域实体上的行为。因此,实体不需要直接引用服务或存储库——它们所拥有的只是一些修改该状态并保持其完整性的状态和行为。 ORM 的工作是将此状态映射到关系数据库中的表。 NHibernate 等 ORM 允许您获得相对较大程度的 persistence ignorance .

更新

Still I don't want to expose method with an INotificationService as a parameter, because this service should be internal, layer above don't need to know about it.

在您当前的 Post 类实现中,INotificationService 具有与该类相同或更高的可见性。如果 INotificationService 是在基础架构层中实现的,则它已经具有足够的可见性。看看hexagonal architecture了解现代架构中分层的概述。

附带说明一下,与通知相关的功能通常可以放入 domain events 的处理程序中.这是一种实现高度解耦的强大技术。

And with separate DTO and domain classes how would you solve persistence synchronization problem when domain object doesn't know about its underlying DTO? How to track changes?

DTO 和相应的域类存在的原因各不相同。 DTO 的目的是跨系统边界传输数据。 DTO 与领域对象不是一一对应的——它们可以表示领域对象的一部分或对领域对象的更改。跟踪更改的一种方法是让 DTO 明确说明它包含的更改。例如,假设您有一个允许编辑 Post 的 UI 屏幕。该屏幕可以捕获所做的所有更改并将这些更改发送到命令 (DTO) 中的服务。该服务将加载适当的 Post 实体并应用命令指定的更改。

关于c# - 在 DDD 中管理持久性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13713060/

相关文章:

c# - 在 C# 中访问非泛型类型

C# OutOfMemory、映射内存文件或临时数据库

c# - .NET 多线程。即时更新 UI

.net - 是否可以将多个模型对象发送到 ASP.NET MVC View ?

architecture - 阅读各种汇编语言的 Material ?

c# - 仅在 web.config 端点 BindingConfiguration 中拥有自定义用户名验证器就足够了吗?

.net - SQL Server 2008 的免费架构导出?

entity-framework - CQRS 是 CRUD 的替代品吗?

architecture - 与云无关的架构?

c# - Visual Studio 2015发布错误