我正在使用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对象分别映射到Order
和OrderLines
CSLA对象
自动映射到OrderLines
时会映射OrderLinesDTO
列表。然后,自动映射器会映射行上的"Order"
属性,然后映射回Order
,然后循环映射回OrderLine
,然后回到Order
,依此类推0} p>
有人知道Automapper是否可以避免此循环引用吗?
答案 0 :(得分: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)
由于这是Google搜索结果的第一名,我认为可能会有像我这样的人来到这里,他们没有遇到stackoverflow异常,但是在将对象(通过ASP.NET)发送到客户端,因此将其序列化为JSON。
因此,我具有相同的结构,Invoice
具有多个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在对象图中的另一个位置遇到相同的实例时,它只是删除对原始实例的引用,而不是复制数据,因此不会引起循环引用问题!
所以现在我不必进一步编辑AutoMapper
的配置。
答案 2 :(得分:1)
我在使用EF 6和AutoMapper 6时遇到了同样的问题。显然,肯尼·卢塞罗(Kenny Lucero)发布的内容使我找到了解决方案。这是AM网站的摘录:
// Circular references between users and groups
cfg.CreateMap<User, UserDto>().PreserveReferences();
在两个模型中添加PreserveReferences()使其起作用。
答案 3 :(得分:0)
不确定是否应该在此处发布:
在方法中执行automapper.map后,我遇到了相同的错误。 CularBytes的答案让我想到这个问题与automapper不相关,而与json有关。
我做到了:
Return ok(_service.getDataById(id));
代替
Return ok(await _service.getDataById(id));
(我忘记等待asyc通话...我知道是菜鸟错误)
答案 4 :(得分:-1)
我遇到了同样的问题,并通过降级到4.2.1解决了该问题。 循环引用的检查显然很昂贵,因此默认情况下不进行检查。 Migrating to AutoMapper 5 - Circular references
假设这些应该是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团队。