[英]Map a list of objects manually using automapper
I am using automapper to map one complex object to another where the source object has a list of objects whose properties do not match the list of objects in the destination.我正在使用 automapper 将一个复杂对象映射到另一个对象,其中源对象有一个对象列表,其属性与目标中的对象列表不匹配。
So, i am manually going through the list in the source using Linq and mapping it to the destination object.因此,我使用 Linq 手动浏览源中的列表并将其映射到目标对象。
The issue is, the destination object is a database object:问题是,目标对象是一个数据库对象:
Source Object:源对象:
public class AutomationDetailsResponse
{
public Guid ServiceId { get; set; }
public int EngagementId { get; set; }
public string ServiceRequestName { get; set; }
public Guid ServiceRequestGUID { get; set; }
public string OfficeId { get; set; }
public string CountryId { get; set; }
public string EngagementCode { get; set; }
public string CanvasDocumentUri { get; set; }
public string CanvasAudienceUri { get; set; }
public List<RequestFile> InputRequestFiles { get; set; }
public List<RequestFile> OutputRequestFiles { get; set; }
public string Status { get; set; }
public string RequestInitiatedByName { get; set; }
public string RequestInitiatedBy { get; set; }
public int DataCenterId { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime LastUpdatedAt { get; set; }
public List<ActivityFeed> ActivityFeeds { get; set; }
public List<Guid> TaskIds { get; set; }
[JsonProperty("Id")]
public int CanvasRequestId { get; set; }
}
public class RequestFile
{
public Guid Id { get; set; }
public int FileSequence { get; set; }
public Guid GroupId { get; set; }
public string GroupName { get; set; }
public string FileType { get; set; }
public string FileName { get; set; }
public int FileSize { get; set; }
public Guid DocumentId { get; set; }
public DateTime CreatedAt { get; set; }
}
public class ActivityFeed
{
public int CreatedById { get; set; }
public DateTime CreatedAt { get; set; }
public string Description { get; set; }
public int ActivityType { get; set; }
public string UserName { get; set; }
public int Id { get; set; }
}
Destination Object:目标对象:
[Table(nameof(AutomationRequest), Schema = Schemas.SAH)]
public class AutomationRequest : EntityBase, ICreatedDate, IModifiedDate
{
[Required]
public int CanvasEnvironmentId { get; set; }
[Required]
public Guid AppInstanceId { get; set; }
public Guid CanvasRequestGUID { get; set; }
public int CanvasRequestId { get; set; }
public int DownstreamStatusId { get; set; }
[Required]
public int CanvasStatusId { get; set; }
[Required]
public Guid ServiceCatalogId { get; set; }
[Required]
public string RequestName { get; set; }
[Required]
[MaxLength(255)]
public string EngagementId { get; set; }
[Required]
public int CountryId { get; set; }
[Required]
public int DataCenterId { get; set; }
public bool IsDeletedFromSAH { get; set; }
public bool IsDeletedFromCAH { get; set; }
[MaxLength(500)]
public string CreatedByEmail { get; set; }
[MaxLength(500)]
public string CreatedByName { get; set; }
[Required]
public DateTime CreatedDate { get; set; }
[MaxLength(38)]
public string ModifiedBy { get; set; }
[MaxLength(50)]
public string OriginatedFrom { get; set; }
[Required]
public DateTime ModifiedDate { get; set; }
public string NavigationUrl { get; set; }
public int? Version { get; set; }
[ForeignKey(nameof(CanvasEnvironmentId))]
public virtual Environment CanvasEnvironment { get; set; }
[ForeignKey(nameof(CountryId))]
public virtual Country Country { get; set; }
[ForeignKey(nameof(ServiceCatalogId))]
public virtual ServiceCatalog ServiceCatalog { get; set; }
[ForeignKey(nameof(CanvasStatusId))]
public virtual AutomationRequestStatus CanvasStatus { get; set; }
public virtual ICollection<AutomationRequestInputFile> InputFiles { get; set; }
public virtual ICollection<AutomationRequestOutputFile> OutputFiles { get; set; }
public virtual ICollection<AutomationRequestTask> Tasks { get; set; }
}
[Table(nameof(AutomationRequestInputFile), Schema = Schemas.SAH)]
public class AutomationRequestInputFile : EntityBase, ICreatedDate, IModifiedDate
{
[Required]
public Guid CanvasGroupId { get; set; }
public Guid CanvasDocumentId { get; set; }
[MaxLength(255)]
public string FileName { get; set; }
[MaxLength(38)]
public string CreatedBy { get; set; }
[Required]
public DateTime CreatedDate { get; set; }
[MaxLength(38)]
public string ModifiedBy { get; set; }
[Required]
public DateTime ModifiedDate { get; set; }
[Required]
public Guid AutomationRequestId { get; set; }
public string FileType { get; set; }
[ForeignKey(nameof(AutomationRequestId))]
public virtual AutomationRequest AutomationRequest { get; set; }
}
public class EntityBase
{
public EntityBase()
{
Id = Guid.NewGuid();
}
public Guid Id { get; set; }
}
This is the mapping configuration:这是映射配置:
CreateMap<AutomationDetailsResponse, AutomationRequest>()
.ForMember(dst => dst.Id, opt => opt.Ignore())
.ForMember(
dst => dst.CanvasRequestGUID,
opt => opt.MapFrom(src => src.ServiceRequestGUID))
.ForMember(
dst => dst.RequestName,
opt => opt.MapFrom(src => src.ServiceRequestName))
.ForMember(
dst => dst.InputFiles,
opt => opt.MapFrom(src => src.InputRequestFiles.Select(x => new AutomationRequestInputFile { CanvasGroupId = x.GroupId, CanvasDocumentId = x.DocumentId, FileName = x.FileName, FileType = x.FileType })))
.ForMember(
dst => dst.OutputFiles,
opt => opt.MapFrom(src => src.OutputRequestFiles.Select(x => new AutomationRequestOutputFile { CanvasDocumentId = x.DocumentId,FileName = x.FileName, FileType = x.FileType, FileSize = x.FileSize, CreatedDate = x.CreatedAt })))
.ForMember(
dst => dst.CreatedByName,
opt => opt.MapFrom(src => src.RequestInitiatedByName))
.ForMember(
dst => dst.CreatedDate,
opt => opt.MapFrom(src => src.CreatedAt))
.ForMember(
dst => dst.ModifiedDate,
opt => opt.MapFrom(src => src.LastUpdatedAt))
.ForMember(
dst => dst.Tasks,
opt => opt.MapFrom(src => src.TaskIds.Select(x => new AutomationRequestTask { CanvasId = x })))
;
The mapping works.映射有效。 The issue is this:问题是这样的:
var automation = await _dbContext.AutomationRequests.FirstOrDefaultAsync(x => x.CanvasRequestGUID == automationDetails.ServiceRequestGUID);
_mapper.Map(automationDetails, automation);
_dbContext.Update(automation);
await _dbContext.SaveChangesAsync();
The update fails because, in the mapping configuration, we are create a new instance AutomationRequestInputFile which triggers the constructor in EntityBase, creating a new Id.更新失败,因为在映射配置中,我们创建了一个新实例 AutomationRequestInputFile,它触发了 EntityBase 中的构造函数,创建了一个新的 Id。 When EF Core tries to update the row, it does not find the record because the Id has changed.当 EF Core 尝试更新该行时,它找不到该记录,因为 Id 已更改。
I have been trying to solve this for 1 day now and havent made any progress.我一直试图解决这个问题 1 天了,但没有取得任何进展。
Any help is appreciated.任何帮助表示赞赏。
Thanks.谢谢。
You're not using AutoMapper correctly since you're still manually constructing the AutomationRequestInputFile
objects (by using LINQ .Select()).您没有正确使用 AutoMapper,因为您仍在手动构建AutomationRequestInputFile
对象(通过使用 LINQ .Select())。
The solution is to add a second mapping for RequestFile
to AutomationRequestInputFile
and remove the Select in the MapFrom config of the ´InputFiles´ property.解决方案是将RequestFile
的第二个映射添加到AutomationRequestInputFile
并删除“InputFiles”属性的 MapFrom 配置中的 Select。
Here's a working .NET Fiddle (properties & types not provided in your question have been omitted): https://dotnetfiddle.net/9qizfk这是一个有效的 .NET Fiddle(您的问题中未提供的属性和类型已被省略): https : //dotnetfiddle.net/9qizfk
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.