映射时如何处理循环引用?

时间:2012-10-17 18:47:16

标签: asp.net-mvc entity-framework automapper

以此数据库为例

员工

  • id - int(PK)
  • name - varchar

薪酬

  • id - int(PK)
  • employee_id - int(FK)
  • 金额 - 浮动

实体框架将生成类似于以下的模型:

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; }
}

Emplyee引用他的薪水清单,而每个薪水都指向他所拥有的员工。这导致循环参考问题。

我遵循存储库模式并使用AutoMapper将Employee转移到EmployeeDTO,将Salary转移到SalaryDTO。我希望那些DTO能够保持其儿童关系的信息。但是,我不想递归地这样做。我可以做类似的事情。

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; }
}

但这会成为维护的噩梦。

我如何告诉AutoMapper只映射一个单独的后代,或实现类似的目标?

2 个答案:

答案 0 :(得分:3)

我最终选择了DTO - ChildDTO路线,因为我找到了一种易于管理的方式。

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
}

这样,影响子DTO的唯一数据库更改就是FK!

我可以通过arround的另一种方式完成它(EmployeeDTO扩展EmployeeChildDTO)并避免Overrides和Virtuals以及IgnoreMaps,但我想将核心DTO保留为基类。

答案 1 :(得分:0)

我不明白为什么这会成为维护的噩梦。我已经做了一段时间同样的事情,它对我来说很好。但需要注意的一点是,您仍然希望SalaryChildDTO类中的员工ID。