我把映射逻辑放在哪里
本文关键字:在哪里 映射 | 更新日期: 2023-09-27 18:25:40
我有一个域模型、一个存储库和实体框架。一般来说,我不希望我的域与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")
的调用堆栈是什么样子的?
搜索只找到了通常引用马丁·福勒的一般回复。我需要一个具体的例子来参考。
问题是我的UserRepository正在返回一个实体框架User DbSet
这不应该是返回类型,因为这会引入耦合。您仍然可以返回该类型,但它应该被多态地解释为不同的类型。
因此,当你可能在你的存储库中做这样的事情时:
return db.Users;
返回类型不应该是实现类型(DbSet<User>
?),而是更通用的类型:
public IQueryable<User> GetUsers()
{
return db.Users;
}
"EF对象"正在整个域中使用,但域并不知道或关心这一点。域将其视为User
模型的可查询集合。
如果您想单独保存域对象,请将它们单独保存。若存储库从持久层返回对象,那个么它就为过度发布问题打开了大门(当前端使用相同的对象时,这尤其危险)。我会将映射逻辑移到另一个类中,并在您的存储库中使用它。
Automapper是一个非常流行的库,用于映射不同的对象,例如Domain对象到DTO,反之亦然。您可以将Automapper注入存储库,并使用它将IEnumerable<EntityFrameworkUser>
映射到IEnumerable<DomainUser>
。第一寄存器映射
Mapper.CreateMap<EntityFrameworkUser, DomainUser>();
然后从您的存储库中调用
return Mapper.Map<IEnumerable<EntityFrameworkUser>, IEnumerable<DomainUser>>(users);
如果有问题的方法的目的只是始终返回指定团队的所有成员,并且您永远不会对结果应用附加子句,则可以将UserRepostory.GetUsersByTeam()
方法的返回类型从EF DbSet<User>
类型更改为List<User>
,然后将返回语句更改为return db.Users.Where(u => u.Team == "MyTeam").ToList()
。
您将不再从存储库级别获取EF对象。