Reputation: 3427
I have a domain model, a repository and entity framework. I don't want my domain tied to EF or the persistence layer in general.
So I created a repository to keep things like db.Users.Where(u => u.Team == "MyTeam")
out of my domain.
After implementing the generic repository pattern if I want a list of users on a particular team I use UserRepository.GetUsersByTeam("MyTeam")
.
The problem is my UserRepository is returning IEnumerable<EntityFrameworkUser>
, instead of IEnumerable<DomainUser>
, and in order to return IEnumerable<DomainUser>
I need to map DomainUser
to EntityFrameworkUser
somewhere.
So where specifically do you map from the EntityFrameworkUser class to the DomainUser class?
Should the repository encapsulate the mapping logic in addition to the query logic?
If I want a collection of domain user objects what does the call stack look like for UserRepository.GetUsersByTeam("MyTeam")
look like?
Searching has only found me general responses that usually quote Martin Fowler. I need a concrete example to refer to.
Upvotes: 2
Views: 1587
Reputation: 2258
If you want to keep domain object separately - keep them separately. If you repository returns objects from persistent layer, then it opens door for over-posting issues (it especially dangerous when front-end uses the same objects). I would move mapping logic into another class and use it in your repositories.
Automapper is very popular library for mapping different object, for example Domain object to DTO and vise versa. You can inject Automapper into your repositories and use it to map IEnumerable<EntityFrameworkUser>
to IEnumerable<DomainUser>
. First register mapping
Mapper.CreateMap<EntityFrameworkUser, DomainUser>();
Then call it from your repository
return Mapper.Map<IEnumerable<EntityFrameworkUser>, IEnumerable<DomainUser>>(users);
Upvotes: 1
Reputation: 8594
If the purpose of the method in question is simply to always return all of the members of the specified team, and you're never going to apply additional clauses to the result, you could change the return type of the UserRepostory.GetUsersByTeam()
method from the EF DbSet<User>
type to List<User>
, then change the return statement to return db.Users.Where(u => u.Team == "MyTeam").ToList()
.
You'll no longer get the EF objects out of the repository level.
Upvotes: -1
Reputation: 218827
The problem is my UserRepository is returning an entity framework User DbSet
That shouldn't be the return type, because that would introduce coupling. You can still return that type, but it should be polymorphically interpreted as a different type.
So while you may be doing something like this in your repository:
return db.Users;
The return type shouldn't be that implementing type (DbSet<User>
?), but something more generic:
public IQueryable<User> GetUsers()
{
return db.Users;
}
The "EF objects" are being used throughout the domain, but the domain doesn't know or care about that. The domain sees it as a queryable collection of User
models.
Upvotes: 2