C# 存储库和服务设计问题
我们正在努力找出使用DDD时的最佳实践,我们正在就什么最有意义或是“正确的方式”进行一些讨论 注意:所有代码都是伪代码。 承认者如下:C# 存储库和服务设计问题,c#,domain-driven-design,service,repository-pattern,C#,Domain Driven Design,Service,Repository Pattern,我们正在努力找出使用DDD时的最佳实践,我们正在就什么最有意义或是“正确的方式”进行一些讨论 注意:所有代码都是伪代码。 承认者如下: public interface IDomainEntityAService { void CreateMyObject(DomainEntityA myobject); DomainEntityA RetrieveDomainEntityA(long someId); //Other operations that handle the
public interface IDomainEntityAService
{
void CreateMyObject(DomainEntityA myobject);
DomainEntityA RetrieveDomainEntityA(long someId);
//Other operations that handle the business logic dealing with MyObject
}
public class DomainEntityB
{
public string Name { get; set; }
public IList<DomainEntityA> DomainEntityAList { get; set; }
}
public class DomainEntityBService : IDomainEntityBService
{
public DomainEntityBService(IDomainEntityAService domainEntityAService, IDomainEntityBRepository repo)
{
}
public DomainEntityB GetDomainEntityB()
{
var domainEntityBDAL = _repo.Get(someId);
DomainEntityB result = new DomainEntityB() { Name = domainEntityBDAL.Name };
foreach (var id in domainEntityBDAL.DomainEntityAListIds)
{
result.DomainEntityAList.Add(_domainEntityAService.Get(id));
}
return result;
}
}
我们还有另一个服务,它使用IDomainEntityAService的一部分来满足特定的需求
public interface IDomainEntityBService
{
DomainEntityB GetDomainEntityB();
}
其中,其他信息包含以下内容:
public interface IDomainEntityAService
{
void CreateMyObject(DomainEntityA myobject);
DomainEntityA RetrieveDomainEntityA(long someId);
//Other operations that handle the business logic dealing with MyObject
}
public class DomainEntityB
{
public string Name { get; set; }
public IList<DomainEntityA> DomainEntityAList { get; set; }
}
public class DomainEntityBService : IDomainEntityBService
{
public DomainEntityBService(IDomainEntityAService domainEntityAService, IDomainEntityBRepository repo)
{
}
public DomainEntityB GetDomainEntityB()
{
var domainEntityBDAL = _repo.Get(someId);
DomainEntityB result = new DomainEntityB() { Name = domainEntityBDAL.Name };
foreach (var id in domainEntityBDAL.DomainEntityAListIds)
{
result.DomainEntityAList.Add(_domainEntityAService.Get(id));
}
return result;
}
}
因为我们希望尽可能地保持干燥,所以理想情况下我们希望重用IDomainEntityAService的逻辑来检索DomainEntityB的DomainEntityList列表。哪一个最有意义
A) 在IDOMainEntityBreposition中引用IDomainEntityAService
e、 g
B) IDomainEntityBRepository只处理SQL内容,我们使用IHaveOtherInformation的服务层来填充MyObject列表
public class DomainEntityBService : IDomainEntityBService
{
public DomainEntityBService(IDomainEntityAService domainEntityAService, IDomainEntityBRepository repo)
{
}
public DomainEntityB GetDomainEntityB()
{
var domainEntityB = _repo.Get(someId);
domainEntityB.DomainEntityAList = _domainEntityAService.GetAll(someId);
return domainEntityB;
}
}
C) 我们为OtherInformation创建一个特定的DAL对象,并使用服务层来组成OtherInformation的实例
public class DomainEntityBDAL
{
public string Name { get; set; }
public IList<int> DomainEntityAListIds { get; set; }
}
D) 哇,我们完全偏离了底线,请改为这样做
我希望这是有意义的,谢谢你的帮助
编辑注释:
public interface IDomainEntityBRepository
{
void Add(DomainEntityB information);
DomainEntityB Get(long someId);
}
也许一个英文描述能更好地描述我的问题。我们有DomainEntityA,它是一个聚合根。有一个相应的服务来处理处理DomainEntityA的所有逻辑
现在我们还有DomainEntityB,它是一个聚合根。但是,DomainEntityB有一个DomainEntityA列表。DomainEntityAs可以独立生存,但是DomainEntityB不能没有DomainEntityAs列表
我们如何在DomainEntityB中加载DomainEntityA项列表并维护DomainEntityA的所有逻辑
在DomainEntityBService中重用DomainEntityAService?是否在DomainEntityBService中创建单独的DomainEntityARepository
我们目前使用EntLib,但更多的是关于设计的信息,而不是DAL实现的信息。我在这里假设您将存储到数据库中 这个问题的答案很大程度上取决于您使用什么作为持久性引擎。如果您已经手工实现了自己的持久化,那么
C
就不是一个选项,因为您将看到N+1查询B
很可能是我的首选,因为它提供了最多的代码重用,希望性能不会太差
话虽如此,如果您使用的是NHibernate之类的东西,我建议您不要使用存储库模式,而是
- 将复杂查询封装为对象(然后可以进行单元测试)
- 直接使用会话
我希望这有帮助 不如改用一个通用接口来插入类型?像这样:
public interface IRepository<T>
{
T Get(object id);
void Save(T value);
void Update(T value);
void Delete(T value);
IList<T> GetAll();
}
公共接口IRepository
{
T Get(对象id);
无效保存(T值);
无效更新(T值);
无效删除(T值);
IList GetAll();
}
无论使用什么实现,都应该能够读取类型并知道它如何适合数据库。简而言之,这就是存储库模式。如果您还没有完全使用Entlib,请探索NHibernate。我发现它很好地补充了存储库模式。我在我的博客上写了很多文章,所以如果你想知道更多,你可以去那里。我们很可能会在DAL中使用EntLib。你知道为什么A被认为是不好的吗?存储库返回从多个位置收集的对象是否是一种不好的做法?e、 要创建域模型的实例,我需要从SQL、XML和文件中查询?或者一个存储库应该只涉及一个数据存储?这个问题的答案不应该指导您使用哪个DAL实现吗?为什么你这么热衷于Entlib?如果某个DAL实现能让这变得更容易,我完全赞成。我们过去使用过Entlib,并计划将其与存储库模式一起使用。感谢您提供的信息,不过请参阅我的编辑。如果T的子级也是聚合根(在完全不同的域中),您将如何处理在存储库中加载这些项?NHibernate可以处理“T的子级”(也称为继承)。我不知道你所说的“聚合根在另一个域中”可能是什么意思,但NHibernate可以处理几乎任何你能想到的关系。我不是说继承,“B”有一个“a”的列表。“A”可以独立使用,也可以被其他服务/应用程序使用。现在“B”需要一个“a”的列表才能成为“B”的有效实例。假设要获得所有的“A”(例如“B”)它需要进行一个webservice调用。那个电话应该在哪里?加载“B”的“A”的调用应该在DAL、服务层或其他地方进行吗?B应该只存储一个标识符列表(可能是整数?)。您应该为每个系统创建存储库实现,其中两个实现都继承了IRepository接口。为了详细说明,您将为系统A(使用web服务)提供一个repo,为系统B提供一个repo(使用NHibernate)。您想要两个不同的存储库的原因是将这两个系统解耦,以便在系统A发生更改时,您可以简单地创建其存储库的新版本,而不会干扰系统B的存储库。这在实践中效果很好。