How can you deal with circular references when map

2019-02-23 05:56发布

问题:

Take this database for example

Employee

  • id - int (PK)
  • name - varchar

Salary

  • id - int (PK)
  • employee_id - int (FK)
  • amount - float

Entity Framework will generate models similar to these:

public partial class Employee
{
    public Employee()
    {
        this.Salaries = new HashSet<Salary>();
    }
    public int id { get; set; }
    public string name { get; set; }
}

public partial class Salary
{
    public int id { get; set; }
    public int employee_id { get; set; }
    public float amount  { get; set; }
    public Employee employee { get; set; }
}

The Emplyee references a list of his Salaries while each Salary points to which employee he owns. This results in a circular reference problem.

I follow a repository pattern and use AutoMapper to transfer Employee to EmployeeDTO and Salary to SalaryDTO. I want those DTOs to keep infomation of it's children relationships. However, I dont want to do this recursively. I COULD do something like.

public partial class EmployeeDTO
{
    public EmployeeDTO()
    {
        this.Salaries = new HashSet<SalaryChildDTO>();
    }
    public int id { get; set; }
    public string name { get; set; }
}

public partial class SalaryChildDTO
{
    public int id { get; set; }
    public float amount  { get; set; }
}

But this would become a maintenance nightmare.

How can I tell AutoMapper to only map a single decendant, or acheive a similar goal?

回答1:

I ended up going the DTO - ChildDTO route because I found an easy to manage way of doing it.

public partial class EmployeeDTO
{
    public int id { get; set; }
    public string name { get; set; }
    public virtual IEnumerable<SalaryChildDTO> Salaries { get; set; } //Notice the Virtual
}

public partial class EmployeeChildDTO : EmployeeDTO
{
    [IgnoreMap] //MAGIC!
    public override IEnumerable<SalaryChildDTO> Salaries { get; set; } //Override! :o
}

public partial class SalaryDTO
{
    public int id { get; set; }
    public int employe_id { get; set; }
    public float amount  { get; set; }
    public virtual EmployeeChildDTO Employee { get; set; } //Notice the Virtual once again
}

public partial class SalaryChildDTO : SalaryDTO
{
    [IgnoreMap] //MAGIC!
    public override EmployeeChildDTO Employee { get; set; } //Override! :o
}

That way, the only database changes that affects the child DTOs are FKs!

I could have done it the other way arround (EmployeeDTO extends EmployeeChildDTO) and avoid Overrides and Virtuals and IgnoreMaps but I wanted to keep the core DTO as the base class.



回答2:

I do not understand why this would be a maintenance nightmare. I've been doing the same thing for a while now and it's working fine for me. One thing to note though is that you still want the employee ID inside the SalaryChildDTO class.