views:

137

answers:

2

I have two entities: Employee and Team.

alt text

What I want is an EmployeeForm that has the Name of the Team.

alt text

How can I achieve this using AutoMapper?

My current "solution" is the following:

Mapper.CreateMap<Employee, EmployeeForm>()
                           .ForMember(dest => dest.TeamName, opt => opt.MapFrom(x => x.GetTeams().FirstOrDefault() != null ? string.Join(", ", x.GetTeams().Select(y=>y.Name)) : "n/a"));

In my opinion this is bad readable.

What I would like to have is a generic method where I can pass an entity, choosing the collection and saying if collection is null return a default value or otherwise choose the property of the collection via lambda expressions.

A: 

You could create a read-only string property on Employee called "TeamNames". Put the list-building logic in there. That way, you've got a property that is testable (vs. the lambda expression) and it will make your mapping easier.

Patrick Steele
your idea sounds not bad, I will try this later =)
Rookian
@Patrick, your solution does not help. You would have duplicate entries. So an employee with two teams would be displayed twice. You could distinct the list, but when paging comes into play you get problems. The total count wouldn't be correct and the row numbers, too. I tried to answer my question, please feel free to review.
Rookian
Not sure how you see duplicate entries being generated (unless you allow an employee to be added to the same team multiple times). I'm simply advocating a string property called Employee.TeamNames (which uses your existing lambda expression to build) and change EmployeeForm.Team to EmployeeForm.TeamNames so automapper will join them without any custom mapping required.
Patrick Steele
Yes I allow to have an employee that is in more than one team
Rookian
Here's what I was suggesting: http://pastebin.com/MMGn4nTy
Patrick Steele
Yes I did understand your suggestion. But as I said, it is possible that an employee is a member of more than one team. This leads to duplications. You could fix this with .Distinct(), but if you want to page this you get trouble, because of wrong row numbers.
Rookian
Perhaps we're straying past your original question of trying to clean up the mapping you originally posted. My solution (when combined with a basic Mapper.CreateMap<Employee,EmployeeForm>()) will not create more than one EmployeeForm for each Employee. I don't think continuing this conversation in comments will clarify anything since I think we're talking about different things.
Patrick Steele
+1  A: 

I rethinked my whole design starting to change the domain model:

alt text

I changed the many-to-many association into two one-to-many associations using a relation table.

With this more easier domain model, I can easily map this into a flat DTO using AutoMapper.

public class TeamEmployeeMapperProfile : Profile
{
    protected override void Configure()
    {
        CreateMap<TeamEmployee, TeamEmployeeForm>();
    }
}

Yes that's all :)

Here is the flat view model object.

alt text

Rookian
If this works for you, that is good. However, I'm not sure I'd be comfortable changing my domain model *only* to allow easier integration with some other utility/library.
Patrick Steele
yes that seems so, but it isn't. It is a problem in general in my opinion. Many-to-many associations are too difficult to handle. I made this experience with NHibernate and now with AutoMapper. But as I said, this is not a problem of the tools it is the association itself.
Rookian