17

我正在使用 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 对象分别映射到OrderCSLAOrderLines对象

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

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

4

6 回答 6

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;
         });
于 2012-07-16T13:48:51.843 回答
8

我在使用 EF 6 和 AutoMapper 6 时遇到了同样的问题。显然 Kenny Lucero 发布的内容让我找到了解决方案。这是来自 AM 网站的摘录:

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

将 PreserveReferences() 添加到两个模型中使其工作。

于 2019-07-21T14:56:28.403 回答
3

我遇到了同样的问题并通过降级到版本 4.2.1 解决了它。显然,循环引用的检查很昂贵,所以他们默认不检查。 迁移到 AutoMapper 5 - 循环引用

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

// 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 团队。

于 2018-11-03T04:23:45.133 回答
3

由于这是排名第一的谷歌搜索结果,我想可能有一些人,比如我,来到这里没有遇到 stackoverflow 异常,但是在将对象(通过 ASP.NET)发送到客户端时遇到了麻烦,并且因此它被 JSON 序列化。

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

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

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

因此o.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;,在您JsonConfiguration将 MVC 添加到您的应用程序时包括在内。

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

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

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

于 2019-04-16T21:24:37.927 回答
1

如果有人使用Mapster(与 AutoMapper 相同的 C# 映射库)

TypeAdapterConfig<TSource, TDestination>
    .NewConfig()
    .PreserveReference(true);

需要用于防止堆栈溢出错误。

于 2021-11-05T12:48:42.917 回答
0

不知道我是否应该在这里发布:

在方法中执行 automapper.map 后,我遇到了同样的错误。CularBytes 的回答让我认为这个问题与自动映射器无关,而是与 json 相关。

我做了:

Return ok(_service.getDataById(id));

代替

Return ok(await _service.getDataById(id));

(我忘了等待一个异步调用......我知道的菜鸟错误)

于 2019-12-18T13:18:04.357 回答