views:

375

answers:

1

Hi!

I have a many to many association between a Team and an Employee.

public class Employee : Entity
{
    public virtual string LastName { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string EMail { get; set; }
    public virtual IList<LoanedItem> LoanedItems { get; private set; }
    public virtual ISet<Team> Teams { get; private set; }

    public Employee()
    {
        if (LoanedItems == null)
        {
            LoanedItems = new List<LoanedItem>();
        }

        if (Teams == null)
        {
            Teams = new HashedSet<Team>();
        }
    }

    public virtual Employee AddTeam(Team team)
    {
        Teams.Add(team);
        team.Employees.Add(this);

        return this;
    }

    public virtual Employee RemoveTeamFromEmployee(Team team)
    {
        Teams.Remove(team);
        team.Employees.Remove(this);

        return this;
    }
}

public class Team : Entity
{
    public virtual string Name { get; set; }
    public virtual ISet<Employee> Employees { get; private set; }

    public Team()
    {
        if (Employees == null)
        {
            Employees = new HashedSet<Employee>();
        }
    }

    public virtual Team RemoveEmployeeFromTeam (Employee employee)
    {
        Employees.Remove(employee);
        employee.Teams.Remove(this);

        return this;
    }

    public virtual Team AddEmployee(Employee employee)
    {
        Employees.Add(employee);
        employee.Teams.Add(this);

        return this;
    }
}

I want to map this into the following DTO.

public class EmployeeForm
{
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public string EMail { get; set; }
    public string TeamName { get; set; }
    public int Id { get; set; }
}

So the TeamName is the one who has to be mapped.

I use the following mapping code:

Mapper.CreateMap<Employee, EmployeeForm>()
    .ForMember(dest=>dest.TeamName, opt => opt.MapFrom(s=>s.Teams.FirstOrDefault().Name));
var mappedresult = Mapper.Map<List<Employee>, List<EmployeeForm>>(result);

The problem is the Employee.Teams member. The Teams collection is eager loaded by the way. So it is there.

When Teams is Null I get a NullReference Exception.

How can I map the name of a team into the DTO?

EDIT: For now I left Automapper and use this cumbersome code instead:

var result = _repository.GetAllView();

var employeeForms = new List<EmployeeForm>();
foreach (Employee employee in result)
{
    var employeeAdded = false;
    foreach (var team in employee.Teams)
    {
        employeeForms.Add(new EmployeeForm
          {
              EMail = employee.EMail,
              FirstName = employee.FirstName,
              LastName = employee.LastName,
              TeamName = team.Name
          });
        employeeAdded = true;
    }

    if (!employeeAdded)
    {
        employeeForms.Add(new EmployeeForm
        {
            EMail = employee.EMail,
            FirstName = employee.FirstName,
            LastName = employee.LastName,
            TeamName = string.Empty
        });
    }
}
return View(employeeForms);

For me this smells pentrating ...

+1  A: 

You get the nullreferenceexception because of FirstOrDefault().Name, so you have to do a null check after firstordefault and tell automapper what you want to return when null. The other parts should workf fine.

Paco
How do I do that in the delegate :/ ?Mapper.CreateMap<Employee, EmployeeForm>() .ForMember(dest => dest.TeamName, opt => opt.MapFrom(s => s.Teams != null ? return s.Teams.First().Name : string.Empty)); --> This does not synactically work.
Rookian
That looks like compiling code, but is the nullreference coming from teams is null, or teams is empty? opt.MapFrom(s => s.Teams.FirstOrDefault() == null ? string.Empty : s.Teams.FirstOrDefault().Name)
Paco
Teams can be null so there it comes from.
Rookian
1. It cannot be null when I see your constructor2. The nullreference exception would throw with parameter "source" from firstordefault instead of "name"
Paco
ah sry I was wrong, I now checked bot and it works :o Thanks!
Rookian