使用Automapper导致堆栈溢出的循环引用

问题描述 投票:13回答:3

我正在使用Automapper将我的NHibernate代理对象(DTO)映射到我的CSLA业务对象

我正在使用Fluent NHibernate来创建映射 - 这很好用

我的问题是Order有一个OrderLines的集合,每个都有Order的参考。

public class OrderMapping : ClassMap<OrderDTO>
{
    public OrderMapping()
    {
        // Standard properties
        Id(x => x.OrderId);
        Map(x => x.OrderDate);
        Map(x => x.Address);

        HasMany<OrderLineDTO>(x => x.OrderLines).KeyColumn("OrderId").Inverse();

        Table("`Order`");
    }
}

public class OrderDTO
{
    // Standard properties
    public virtual int OrderId { get; set; }
    public virtual DateTime OrderDate { get; set; }
    public virtual string Address { get; set; }

    // Child collection properties
    public virtual IList<OrderLineDTO> OrderLines { get; set; } <-- this refs the lines
}

和:

public class OrderLineMapping : ClassMap<OrderLineDTO>
{
    public OrderLineMapping()
    {
        // Standard properties
        Id(x => x.OrderLineId);
        References<OrderDTO>(x => x.Order).Column("OrderId");
        Map(x => x.Description);
        Map(x => x.Amount);

        Table("`OrderLine`");
    }
}

public class OrderLineDTO
{
    // Standard properties
    public virtual int OrderLineId { get; set; }
    public virtual string Description { get; set; }
    public virtual decimal Amount { get; set; }

    public virtual OrderDTO Order { get; set; } // <-- this refs the order
}

这些DTO对象分别映射到OrderOrderLines CSLA对象

当自动映射到OrderLines时,会映射OrderLinesDTO列表。然后,自动映射器将"Order"属性映射到线上,然后映射回Order,然后循环映射回OrderLine,然后再映射到Order等等。

有谁知道Automapper是否可以避免此循环引用?

c# circular-reference csla automapper-2
3个回答
23
投票

在您的Automapper配置中:

Mapper.Map<OrderLine, OrderLineDTO>()
    .ForMember(m => m.Order, opt => opt.Ignore());

Mapper.Map<Order, OrderDTO>()
    .AfterMap((src, dest) => { 
         foreach(var i in dest.OrderLines) 
             i.Order = dest;
         });

1
投票

由于这是#1谷歌搜索结果,我认为可能有些人,像我一样,来到这里没有得到stackoverflow异常,但在将对象(通过ASP.NET)发送到客户端时发现问题,因此它是JSON序列化的。

所以我有相同的结构,Invoices有多个InvoiceLines,当我加载Invoice并使用Linq-to-SQL .Include(x => x.InvoiceLines)当我尝试从Api加载对象时我得到错误,因为每个InvoiceLine再次包含相同的Invoice

要解决此问题,请在ASP.NET Core Startup类中执行以下操作:

services.AddMvc().AddJsonOptions(o =>
{
    o.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    o.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
    o.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
    // ^^ IMPORTANT PART ^^
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

因此,在将MVC添加到应用程序时,请在o.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;中包含JsonConfiguration

JSON.Net正在采取额外步骤,使用名为“$ id”的附加元属性设置每个引用。当JSON.Net在对象图中的另一个位置遇到相同的实例时,它只是删除对原始实例的引用,而不是复制数据,因此不会导致循环引用问题!

资料来源:https://johnnycode.com/2012/04/10/serializing-circular-references-with-json-net-and-entity-framework/

所以现在我不必进一步编辑我的AutoMapper配置。


-1
投票

我遇到了同样的问题,并通过降级到版本4.2.1解决了这个问题。显然,循环引用的检查是昂贵的,所以他们默认不检查。 Migrating to AutoMapper 5 - Circular references

据推测,这些应该是v 5+的设置方法,但它不适用于我的数据模型,因为我们选择复杂的dto关系而不是单独使用dtos进行每个操作。

// Self-referential mapping
cfg.CreateMap<Category, CategoryDto>().MaxDepth(3);

// Circular references between users and groups
cfg.CreateMap<User, UserDto>().PreserveReferences();

http://docs.automapper.org/en/stable/5.0-Upgrade-Guide.html#circular-references

Automapper应该能够静态地确定v6.1 +中的循环引用设置,所以如果它在版本v6.1中不能自动运行,请联系automapper团队。

© www.soinside.com 2019 - 2024. All rights reserved.