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.
So, i am manually going through the list in the source using Linq and mapping it to the destination object.
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. When EF Core tries to update the row, it does not find the record because the Id has changed.
I have been trying to solve this for 1 day now and havent made any progress.
Any help is appreciated.
Thanks.
_dbContext.AutomationRequests.Update(automation)instead of_dbContext.Update(automation);