Asp.net mvc 映射时如何处理循环引用?

Asp.net mvc 映射时如何处理循环引用?,asp.net-mvc,entity-framework,automapper,Asp.net Mvc,Entity Framework,Automapper,以这个数据库为例 员工 id-int(PK) 名称-varchar 工资 id-int(PK) 员工id-内部(FK) 金额-浮动 实体框架将生成与以下类似的模型: public partial class Employee { public Employee() { this.Salaries = new HashSet<Salary>(); } public int id { get; set; } public s

以这个数据库为例

员工

  • id-int(PK)
  • 名称-varchar
工资

  • id-int(PK)
  • 员工id-内部(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; }
}
公共部分类员工
{
公职人员()
{
this.palaries=newhashset();
}
公共int id{get;set;}
公共字符串名称{get;set;}
}
公共部分类工资
{
公共int id{get;set;}
public int employee_id{get;set;}
公共浮动金额{get;set;}
公共雇员雇员{get;set;}
}
雇员参考他的工资清单,而每个工资都指向他拥有的雇员。这导致了一个循环参考问题

我遵循存储库模式,使用AutoMapper将员工转移到EmployeeDTO,将工资转移到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; }
}
公共部分类EmployeeDTO
{
公共雇员人数()
{
this.palaries=newhashset();
}
公共int id{get;set;}
公共字符串名称{get;set;}
}
公共部分类工薪儿童
{
公共int id{get;set;}
公共浮动金额{get;set;}
}
但这将成为维护的噩梦


我如何告诉AutoMapper只映射一个Decentant,或者实现一个类似的目标?

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

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

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
}
公共部分类EmployeeDTO
{
公共int id{get;set;}
公共字符串名称{get;set;}
公共虚拟IEnumerable{get;set;}//请注意
}
公共部分类EmployeeChildTo:EmployeeDTO
{
[IgnoreMap]//魔法!
公共覆盖IEnumerable{get;set;}//override!:o
}
公共部分类工资
{
公共int id{get;set;}
public int employee_id{get;set;}
公共浮动金额{get;set;}
public virtual EmployeeChildDTO Employee{get;set;}//再次注意虚拟
}
公共部分类工薪儿童:工薪儿童
{
[IgnoreMap]//魔法!
public override EmployeeChildDTO Employee{get;set;}//override!:o
}
这样,影响子DTO的唯一数据库更改就是FKs


我本可以反过来做的(EmployeeDTO扩展EmployeedChildTo)避免覆盖、虚拟和IgnoreMap,但我希望保留核心DTO作为基类。

因为它使您在添加/修改模型/数据库时必须手动更改的类数量增加了一倍,并且使需要配置的映射数量增加了三倍。这是真的。但是,如果您想将域模型与应用程序的其余部分分离开来,这是无法避免的。如果项目中的域对象数量不是100个,那么创建一个DTO甚至多个与您拥有的每个业务操作相关的DTO是完全可以的。而且AutoMapper应该让你的生活比自己做所有的映射管道容易得多。在您的域和DTO层中维护更改要比在UI层或服务层中使用域层所导致的其他问题好得多。我很难接受的是,AutoMapper实际上并没有让我的生活更轻松,因为如果我在域中进行更改,我必须应用多少更改对象我不需要为项目中的每个DTO创建子类,而只需要手动映射,这将导致几乎相同的工作量。。。。这就是为什么,在我的脑海里,一定有另一种方式。。。。我只是觉得这不对……不,工作量还是不一样。在大多数情况下,DTO看起来非常像域对象。AutoMapper足够智能,可以映射命名类似的属性,但也足够强大,允许您在不需要的情况下配置属性之间的映射。我的意思是,如果您手动将EF POCOs映射到DTO,则不需要创建“ChildDTO”因此,您只需将编写子DTO的时间替换为编写手动映射。从长远来看,这是如何实现的?在维护方面还可以吗?@Korijn由于其他原因,我最终没有使用它(或者过了一段时间后恢复)。我将取消这个答案的标记,因为我不能给出一个跟进。