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 IdPerson: IProvider
Guid Id string FirstName string LastNameBusiness: IProvider
Guid Id string NameService
Guid Id IProvider providerTherefore 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 aggregat开发者_如何学Goe 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?
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.
精彩评论