C# 在DDD中管理持久性

C# 在DDD中管理持久性,c#,.net,architecture,domain-driven-design,persistence,C#,.net,Architecture,Domain Driven Design,Persistence,假设我想创建一个博客应用程序,使用以下两个简单的持久性类:EF Code First或NHibernate,并从存储库层返回: 公共类后持久性 { 公共int Id{get;set;} 公共字符串文本{get;set;} 公共IList喜欢{get;set;} } 像持久性这样的公共类 { 公共int Id{get;set;} //…其他一些属性 } 我想不出一个干净的方法来将我的持久性模型映射到域模型。我希望我的Post域模型界面如下所示: 公共接口IPost { int Id{get;}

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

公共类后持久性
{
公共int Id{get;set;}
公共字符串文本{get;set;}
公共IList喜欢{get;set;}
}
像持久性这样的公共类
{
公共int Id{get;set;}
//…其他一些属性
}
我想不出一个干净的方法来将我的持久性模型映射到域模型。我希望我的
Post
域模型界面如下所示:

公共接口IPost
{
int Id{get;}
字符串文本{get;set;}
公共IEnumerable喜欢{get;}
空样();
}
下面的实现是什么样子的?也许是这样的:

公共类帖子:IPost
{
私有只读后持久性_后持久性;
私有只读INotificationService(通知服务);
公共整数Id
{ 
获取{return\u postPersistence.Id}
}
公共字符串文本
{ 
获取{return\u postPersistence.Text;}
设置{u postPersistence.Text=value;}
}
公众喜欢的人数不胜数
{
//这似乎真的不合适
return _postPersistence.Likes.Select(likePersistence=>newlike(likePersistence));
}
公共邮政(PostPersistence PostPersistence、INotificationService notificationService)
{
_后持久性=后持久性;
_notificationService=notificationService;
}
公共类
{
_postPersistence.Likes.Add(新的LikePersistence());
_notificationService.NotifyPostLike(Id);
}
}

我花了一些时间阅读了DDD,但大多数示例都是理论性的,或者在域层使用了相同的ORM类。我的解决方案看起来真的很难看,因为事实上域模型只是ORM类的包装,它似乎不是一种以域为中心的方法。另外,
IEnumerable Likes
的实现方式也让我感到困扰,因为它不会从LINQ到SQL中受益。使用更透明的持久化实现创建域对象还有哪些(具体的!)选项?

我认为您需要做更多的研究,查看所有选项,并确定是否真的值得花时间实现完整的DDD,过去几天我自己也在那里,所以我将告诉您我的经验

EF代码第一是很有前途的,但有相当多的问题,我这里有一个条目 . 使用EF,您的域模型可以由EF持久化,而无需创建单独的“持久化”类。您可以使用POCO(普通的旧对象)启动并运行一个简单的应用程序,但正如我所说的,它还没有完全成熟

如果使用LINQtoSQL,那么最常见的方法是手动将“数据传输对象”映射到业务对象。对于大型应用程序来说,手动操作可能很困难,所以请检查Automapper之类的工具。或者,您可以简单地将DTO封装在业务对象中,如

  public class Post
   {
      PostPersistence Post { get; set;}
      public IList<LikePersistence> Likes { get; set; }
       .....
   }
公共类职位
{
后持久性Post{get;set;}
公共IList喜欢{get;set;}
.....
}
不确定,很久没用过了


我对这一点的感觉(这只是一种观点,我可能错了)是,你总是必须做出妥协,你不会找到一个完美的解决方案。如果你再给EF几年时间,它可能会达到目标。我认为将DTO映射到DDD对象的方法可能是最灵活的,因此寻找自动映射工具可能是值得的。如果你想保持它的简单,我最喜欢的是在需要的时候围绕DTO进行一些简单的包装。

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

更新

不过,我还是不想将INotificationService的方法公开为 参数,因为此服务应该是内部的,所以上面的层不 我需要知道这件事

在当前的
Post
类实现中,
INotificationService
与该类具有相同或更高的可见性。如果
INotificationService
是在基础架构层中实现的,则它必须具有足够的可见性。请参阅,了解现代建筑分层的概述

作为旁注,与通知相关联的功能通常可以放在处理程序中,以供使用。这是实现高度解耦的强大技术

对于单独的DTO和域类,您将如何解决 域对象不知道时的持久性同步问题 关于它的底层DTO?如何跟踪变化

DTO和相应的域类存在的原因非常不同。DTO的目的是跨系统边界传输数据。DTO与域对象不是一一对应的-它们可以