Reputation: 389
I am trying to use timestamps in my application for when a row was created and last modified. When mapping a DTO to an entity, properties are overwritten and set to null when they originally had a value. (note i'm using CQRS to handle the commands)
This is my base entity which every EF Core entity inherits
public class BaseEntity : IBaseEntity, IDeletable
{
public int Id { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTimeOffset? DateCreated { get; set; }
public string CreatedBy { get; set; }
public string LastModifiedBy { get; set; }
public DateTimeOffset DateModified { get; set; } = DateTimeOffset.UtcNow;
public bool IsDeleted { get; set; }
public string DeletedBy { get; set; }
public DateTimeOffset? DateDeleted { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
}
The DTO which is used for the request is:
public sealed class UpdateCustomerCommand : IRequest<Result<int>>
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string PrimaryContact { get; set; }
public string SecondaryContact { get; set; }
public ICollection<AddressCreateDto> Addresses { get; set; }
}
note that I don't include the properties that are in BaseEntity because EF Core should generate those values automatically, I don't think when making a request anyone would need to worry about a property called DateCreated etc… it's simply for auditing purposes
var repository = _unitOfWork.GetRepository<Customer>();
var customer = await repository.FindAsync(request.Id, cancellationToken);
if (customer == null) throw new KeyNotFoundException();
var mappedCustomer = _mapper.Map<Customer>(request);
await repository.UpdateAsync(request.Id, mappedCustomer);
When I retrieve the object using the FindAsync(request.Id, cancellationToken)
method, the values are there, but after I do the mapping, they are overwritten.
Here is the mapping.
CreateMap<UpdateCustomerCommand, Customer>()
.ForMember(dst => dst.Addresses, opt => opt.MapFrom(src => src.Addresses))
.ReverseMap();
Upvotes: 1
Views: 497
Reputation: 3779
If you don't want those properties to be mapped, you have to specifically state that when you create the mapping. Depending on the version of AutoMapper you're using, you'll either need to ignore the mapping or use DoNotValidate.
// Old
cfg.CreateMap<Source, Dest>()
.ForMember(dest => dest.DateModified, opt => opt.Ignore());
// New
cfg.CreateMap<Source, Dest>()
.ForMember(dest => dest.DateModified, opt => opt.DoNotValidate());
Here's a link to the documentation:
Upvotes: 1