DDD、存储库和角色接口
我非常感谢人们对以下设计问题的意见。
我有一个模型,其中“人”或“企业”可能是某种“服务”的提供者。类定义示例如下所示:
IProvider
Guid ID
人员:IProvider
Guid ID
字符串 名字
字符串姓氏
公司:IProvider
Guid ID
字符串名称
服务
Guid ID
IProvider 提供商
因此,我在我的域中创建了相关概念:“个人”、“业务”、“IProvider”和“服务”。我遇到困难的是创建存储库的实体。在这种情况下,“服务”是一个聚合根,因此有自己的存储库。在我的上下文中,“业务”也是一个聚合根,因为即使它不是提供者,它也有意义。仅当“人员”是“提供者”时,才会在系统中创建“人员”。
我是否会为 IProvider 角色创建一个存储库,它会返回“Person”和“Business”的实例?我的问题是,代码可能很快就会变得非常复杂,因为任何实现都需要查看多个表等以返回所有不同类型的 IProvider。这种方法需要创建“人员”和“业务”的存储库并将其注入“IProvider”存储库以提供所需的功能,即
public class ProviderRepository : IProviderRepoistory
{
public IBusinessRepository businessRepository {get; set; }
public IPersonRepository personRepository {get; set; }
public IProvider FindById(Guid Id){
IProvider entity = businessRepository.FindById(Id);
if(entity == null)
entity = personRepository.FindById(Id);
return entity;
}
}
另一种方法是为实现“人员”和“业务”实体创建存储库一个“IProvider”接口,因此使它们可以参与该角色。即,
public class PersonRepository : IPersonRepository, IProviderRepository
{
private ISession session;
public Person FindById(Guid Id){
return session.Query<Person>().FirstOrDefault<Person>(x => x.Id == Id);
}
public IProvider FindById(Guid Id){
return session.Query<Person>().FirstOrDefault<Person>(x => x.Id == Id && x.IsProvider == true);
}
}
我将在需要时使用一种机制(即 IoC 容器)来选择 IProviderRepository 的正确具体实现。例如,如果我正在与一个我知道是个人的提供者打交道,我可以获得 PersonRepository 实现。
另一种选择是不实现任何 IProvider 存储库,而只使用“Person”和“Business”存储库并根据服务层的需要使用它们?
I would really appreciate peoples opinions on the below design problem.
I have a model in which either a ‘Person’ or a ‘Business’ may be the provider of a certain ‘Service’. An example class definition is shown below:
IProvider
Guid Id
Person: IProvider
Guid Id
string FirstName
string LastName
Business: IProvider
Guid Id
string Name
Service
Guid Id
IProvider provider
Therefore I have created the relevant concepts in my domain, ‘Person’, ‘Business’, ‘IProvider’ and ‘Service’. Where I am struggling is on which entities to create the repositories. In this context ‘Service’ is an aggregate root and therefore has its own repository. ‘Business’ is also an aggregate root in my context as it will have meaning even if it is not a provider. ‘Person’ will only be created in the system if they ‘are a Provider’.
Would I create a repository for the role of IProvider, which would return me instances of ‘Person’ and ‘Business’; my issues with this are that the code could quickly become quite complicated as any implementation would need to look at multiple tables etc to return all different type of IProvider. Such an approach would require repositories for ‘Person’ and ‘Business’ to be created and injected into the ‘IProvider’ repository to provide the required functionality i.e.
public class ProviderRepository : IProviderRepoistory
{
public IBusinessRepository businessRepository {get; set; }
public IPersonRepository personRepository {get; set; }
public IProvider FindById(Guid Id){
IProvider entity = businessRepository.FindById(Id);
if(entity == null)
entity = personRepository.FindById(Id);
return entity;
}
}
Another appraoch would be to create repositories for the 'Person' and 'Business' entities which implement a 'IProvider' interface, therefore making them available to participate in that role. i.e
public class PersonRepository : IPersonRepository, IProviderRepository
{
private ISession session;
public Person FindById(Guid Id){
return session.Query<Person>().FirstOrDefault<Person>(x => x.Id == Id);
}
public IProvider FindById(Guid Id){
return session.Query<Person>().FirstOrDefault<Person>(x => x.Id == Id && x.IsProvider == true);
}
}
I would then use a mechinism (i.e. IoC container) to pick the correct concrete implementation of the IProviderRepository when required. For example if I am dealing with a provider who I know to be a person I can get the PersonRepository implementation.
Another option would be to not implement any IProvider repositories and just stick with ‘Person’ and ‘Business’ repositories and use them as required in the service layer?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为你想得太多了,并且过早地尝试优化。
从您在这里所说的一切来看,对我来说,个人和业务都是实体,但两者都不是聚合(尽管显然,我可能在您与领域专家的讨论中遗漏了一些内容)。在我看来,提供者是一个集合。
当您构建 ProviderRepository 时,您不需要为企业和人员注入存储库,b/c 如果它们不是聚合,则它们不应该拥有自己的存储库。相反,ProviderRepository 应该直接使用 Session 从您提出的任何数据库模式中获取所需的内容,以组成给定查询的相关实体。如果正确映射继承,则可以对基类或接口进行查询。
I think you're over thinking it, and you're trying to optimize too early.
From everything you've said here, it sounds to me like Person and Business are both entities, but neither is an aggregate (though obviously, I might be missing something in your discussions w/ domain experts). It seems to me that the Provider is the aggregate.
When you build the ProviderRepository, you don't need to inject repositories for Businesses nad Persons, b/c if they're not aggregates, they shouldn't have their own repositories. Instead, the ProviderRepository should use the Session directly to fetch what it needs from whatever DB schema you come up with to compose the entities in question for the given query. If you map the inheritance correctly, you can do queries on the base class or interface.