简体   繁体   English

使用 automapper 手动映射对象列表

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM