我在哪里放置映射逻辑?

时间:2015-12-03 14:13:36

标签: c# entity-framework repository-pattern datamapper

我有一个域模型,一个存储库和实体框架。我不希望我的域名依赖于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的一般回复。我需要一个具体的例子来引用。

3 个答案:

答案 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对象。