我把映射逻辑放在哪里

本文关键字:在哪里 映射 | 更新日期: 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对象。