我使用AutoMapper将Linq-to-SQL对象映射到域模型。此Linq-to-SQL对象具有子对象。将Linq-to-SQL对象映射到其域模型后,所有值都是正确的。但是,在将域模型映射回它的Linq-to-SQL对应物后,所有子对象都会丢失其父ID。
我已将其缩小到AutoMapper的EnumerableMapper类中的SetElementValue()方法。子对象引用(在SetElementValue()中名为mappedValue的参数)保持它的父id,直到它被添加到枚举中,在这种情况下,它是IBindingList的实现。在添加到所述实现之后,它的父id被设置为0.我已经比较了Linq-to-SQL对象和域模型对象中的所有值,并且除了父id之外,所有值都等于它们的原始状态。
我倾向于认为这与IBindingList的使用有关,在这里删除父ID是否有意义?我忽略了什么吗?我不确定您需要哪些源代码来提供任何有用的建议,只需询问并且您将收到您需要的任何内容。
活动(父)域模型定义:
public class Activity : IActivityEntity
{
public int Id { get; set; }
public string NameOrDescription { get; set; }
public int ClientId;
public int ActivityTypeId;
public int PerformedByEmployeeId;
public bool IsBillable;
public DateTime PerformedDate { get; set; }
public DateTime StartTime { get; set; }
public DateTime StopTime { get; set; }
public string Description { get; set; }
public int ProjectId;
public int WorkOrderId;
public IList<ProductLine> ProductLines;
public Activity()
{
this.ProductLines = new List<ProductLine>();
}
public Activity(ActivityType activityType, int clientId, int employeeId, int workOrderId, DateTime startTime, DateTime stopTime, DateTime performedDate, string description)
{
this.ClientId = clientId;
this.ActivityTypeId = activityType.Id;
this.PerformedByEmployeeId = employeeId;
this.Description = description ?? "";
this.IsBillable = activityType.IsBillable;
this.StartTime = startTime;
this.StopTime = stopTime;
this.PerformedDate = performedDate;
this.WorkOrderId = workOrderId;
}
}
ProductLine(子)域模型定义:
public class ProductLine : IEntity
{
public int Id;
public int ClientId;
public int ProductId;
public int ProductGroupId;
public string ProductNumber;
public int SupplierId;
public string Name;
public int ActivityId;
public int WorkOrderId;
public float Amount;
public decimal InPriceWithoutVAT;
public decimal OutPriceWithoutVAT;
public bool IsBillable;
public double? DiscountPercentage;
public string Denomination;
public bool CreatedBySystem;
public bool StructureProductLine;
public int SellerEmployeeId;
public int ConsultantEmployeeId;
public ProductLine()
{
}
}
活动域到DTO规则:
Mapper.CreateMap<Activity, D.Activity>()
.ForMember(dto => dto.ActivityID, options => options.MapFrom(activity => activity.Id))
.ForMember(dto => dto.ClientID, options => options.MapFrom(activity => activity.ClientId))
.ForMember(dto => dto.ActivityTypeID, options => options.MapFrom(activity => activity.ActivityTypeId))
.ForMember(dto => dto.Description, options => options.MapFrom(activity => activity.Description))
.ForMember(dto => dto.StartTime, options => options.MapFrom(activity => activity.StartTime))
.ForMember(dto => dto.StopTime, options => options.MapFrom(activity => activity.StopTime))
.ForMember(dto => dto.IsBillable, options => options.MapFrom(activity => activity.IsBillable))
.ForMember(dto => dto.WorkOrderID, options => options.MapFrom(activity => activity.WorkOrderId))
.ForMember(dto => dto.PerformedByEmployeeID, options => options.MapFrom(activity => activity.PerformedByEmployeeId));
ProductLine域到DTO规则:
Mapper.CreateMap<ProductLine, D.ProductLine>()
.ForMember(dto => dto.ProductLineID, options => options.MapFrom(productLine => productLine.Id))
.ForMember(dto => dto.ActivityID, options => options.MapFrom(productLine => productLine.ActivityId))
.ForMember(dto => dto.Amount, options => options.MapFrom(productLine => productLine.Amount))
.ForMember(dto => dto.Billable, options => options.MapFrom(productLine => productLine.IsBillable))
.ForMember(dto => dto.ClientID, options => options.MapFrom(productLine => productLine.ClientId))
.ForMember(dto => dto.Name, options => options.MapFrom(productLine => productLine.Name))
.ForMember(dto => dto.OutPriceWithoutWAT, options => options.MapFrom(productLine => productLine.OutPriceWithoutVAT))
.ForMember(dto => dto.ProductGroupID, options => options.MapFrom(productLine => productLine.ProductGroupId))
.ForMember(dto => dto.ProductID, options => options.MapFrom(productLine => productLine.ProductId))
.ForMember(dto => dto.ProductNumber, options => options.MapFrom(productLine => productLine.ProductNumber))
.ForMember(dto => dto.StructureProductLine, options => options.MapFrom(productLine => productLine.StructureProductLine))
.ForMember(dto => dto.SupplierID, options => options.MapFrom(productLine => productLine.SupplierId))
.ForMember(dto => dto.InPriceWithoutWAT, options => options.MapFrom(productLine => productLine.InPriceWithoutVAT))
.ForMember(dto => dto.Denomination, options => options.MapFrom(productLine => productLine.Denomination))
.ForMember(dto => dto.SoldByEmployeeID, options => options.MapFrom(productLine => productLine.SellerEmployeeId))
.ForMember(dto => dto.ConsultantEmployeeID, options => options.MapFrom(productLine => productLine.ConsultantEmployeeId))
.ForMember(dto => dto.WorkOrderID, options => options.MapFrom(productLine => productLine.WorkOrderId));
答案 0 :(得分:0)
我终于找到了解决问题的方法。我没有回答为什么会出现这种情况,但我现在确实有办法绕过它。
代码:
Mapper.CreateMap<Activity, D.Activity>()
.ForMember(dto => dto.ActivityID, options => options.MapFrom(activity => activity.Id))
.ForMember(dto => dto.ClientID, options => options.MapFrom(activity => activity.ClientId))
.ForMember(dto => dto.ActivityTypeID, options => options.MapFrom(activity => activity.ActivityTypeId))
.ForMember(dto => dto.Description, options => options.MapFrom(activity => activity.Description))
.ForMember(dto => dto.StartTime, options => options.MapFrom(activity => activity.StartTime))
.ForMember(dto => dto.StopTime, options => options.MapFrom(activity => activity.StopTime))
.ForMember(dto => dto.IsBillable, options => options.MapFrom(activity => activity.IsBillable))
.ForMember(dto => dto.WorkOrderID, options => options.MapFrom(activity => activity.WorkOrderId))
.ForMember(dto => dto.PerformedByEmployeeID, options => options.MapFrom(activity => activity.PerformedByEmployeeId))
.ForMember(dto => dto.ProductLines, options => options.Ignore())
.AfterMap((src, dest) =>
{
foreach (var productLine in src.ProductLines)
{
dest.ProductLines.Add(Mapper.Map<D.ProductLine>(productLine));
}
});
<强>解释强>
D.ProductLine的字段ActivityID将始终使用之前的AutoMapper规则设置为零,原因我无法解释,但仅当D.ProductLine是D.Activity或任何其他对象的子项时。如果我自己只映射D.ProductLine,那么ActivityID就是正确的。经过8个小时的打击和研究后,我找到了Merenzo在Automapper overwrites missing source property on list with child objects的答案,我可以根据自己的情况调整这些答案。
通过告诉AutoMapper忽略Activity.ProductLines,我可以像Merenzo一样,在完成所有其他映射后,使用AfterMap()映射到D.ProductLine。因此映射D.ProductLine而不使用AutoMapper“意识到它是D.Activity的子对象,拒绝将D.ProductLine.ActivityID设置为零。
如上所述,我无法解释AutoMapper的这种行为,但我现在可以根据我的需要规避它。如果有人对此行为有更好的解决方案或解释,请不要犹豫发布:)