我有一个域模型,一个存储库和实体框架。我不希望我的域名依赖于EF或持久层。
所以我创建了一个存储库来保存db.Users.Where(u => u.Team == "MyTeam")
之类的东西。
在实现通用存储库模式后,如果我想要特定团队的用户列表,我使用UserRepository.GetUsersByTeam("MyTeam")
。
问题是我的UserRepository返回IEnumerable<EntityFrameworkUser>
而不是IEnumerable<DomainUser>
,为了返回IEnumerable<DomainUser>
,我需要将DomainUser
映射到EntityFrameworkUser
某个地方
那么具体是从EntityFrameworkUser类映射到DomainUser类的?
除了查询逻辑之外,存储库是否应该封装映射逻辑?
如果我想要一个域用户对象的集合,UserRepository.GetUsersByTeam("MyTeam")
的调用堆栈是什么样的?
搜索只发现了我通常引用Martin Fowler的一般回复。我需要一个具体的例子来引用。
答案 0 :(得分:1)
问题是我的UserRepository正在返回一个实体框架User DbSet
那不应该是返回类型,因为这会引入耦合。您仍然可以返回该类型,但应将其多态解释为其他类型。
所以,虽然你可能在你的存储库中做了类似的事情:
return db.Users;
返回类型不应该是实现类型(DbSet<User>
?),而是更通用的东西:
public IQueryable<User> GetUsers()
{
return db.Users;
}
&#34; EF对象&#34;正在整个域中使用,但域名不知道或不关心。该域将其视为User
模型的可查询集合。
答案 1 :(得分:1)
如果您想单独保留域对象 - 请单独保留它们。如果存储库从持久层返回对象,则会为over-posting问题打开大门(当前端使用相同的对象时,这尤其危险)。我会将映射逻辑移动到另一个类中,并在您的存储库中使用它。
Automapper是非常流行的库,用于映射不同的对象,例如Domain对象到DTO,反之亦然。您可以将Automapper注入您的存储库,并使用它将IEnumerable<EntityFrameworkUser>
映射到IEnumerable<DomainUser>
。第一个寄存器映射
Mapper.CreateMap<EntityFrameworkUser, DomainUser>();
然后从您的存储库中调用它
return Mapper.Map<IEnumerable<EntityFrameworkUser>, IEnumerable<DomainUser>>(users);
答案 2 :(得分:-1)
如果相关方法的目的只是始终返回指定团队的所有成员,并且您永远不会对结果应用其他子句,则可以更改{的返回类型从UserRepostory.GetUsersByTeam()
类型到DbSet<User>
的{1}}方法,然后将return语句更改为List<User>
。
您将不再从存储库级别获取EF对象。