Automapper - может ли он отображать только существующие свойства в исходных и целевых объектах?
У меня есть простая функция обновления:
public void Update(Users user)
{
tblUserData userData = _context.tblUserDatas.Where(u => u.IDUSER == user.IDUSER).FirstOrDefault();
if (userData != null)
{
Mapper.CreateMap<Users, tblUserData>();
userData = Mapper.Map<Users, tblUserData>(user);
_context.SaveChanges()
}
}
userData - это объект EF, и его свойство Entity Key получает нулевое значение, поскольку, я считаю, оно существует в целевом объекте, но не в исходном объекте, поэтому оно получает сопоставление с его значением по умолчанию (для ключа Entity Key, что null)
Итак, мой вопрос в том, может ли Automapper быть настроен только для того, чтобы сопоставлять свойства, существующие как в исходном, так и в целевом объектах? Я бы хотел, чтобы такие вещи, как Ключ сущности и свойства навигации, были пропущены.
Ответы
Ответ 1
Вы можете явно указать AutoMapper
на Ignore
определенные свойства, если это необходимо:
Mapper.CreateMap<Users, tblUserData>()
.ForMember(dest => dest.Id, opt => opt.Ignore());
который будет означать, что столбец идентификатора в целевом объекте ВСЕГДА останется нетронутым.
Вы можете использовать параметр Condition
, чтобы указать, применяется ли отображение в зависимости от результата логического условия, например:
Mapper.CreateMap<Users, tblUserData>()
.ForMember(dest => dest.Id, opt => opt.Condition(src=>src.Id.HasValue));
или
Mapper.CreateMap<Users, tblUserData>()
.ForMember(dest => dest.Id, opt => opt.Condition(src=>src.Id != null));
в зависимости от ваших конкретных требований.
Ответ 2
Вы можете сказать AutoMapper игнорировать поля, которые вы не хотите отображать так:
userData = Mapper.Map<Users, tblUserData>(user).ForMember(m => m.EntityKey, opt => opt.Ignore());
Ответ 3
Вы можете переопределить это поведение, указав небольшой метод расширения, чтобы игнорировать все свойства, которые не существуют в целевом типе.
public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
var sourceType = typeof(TSource);
var destinationType = typeof(TDestination);
var existingMaps = Mapper.GetAllTypeMaps().First(x => x.SourceType.Equals(sourceType)
&& x.DestinationType.Equals(destinationType));
foreach (var property in existingMaps.GetUnmappedPropertyNames())
{
expression.ForMember(property, opt => opt.Ignore());
}
return expression;
}
Тогда можно сделать отображение следующим образом:
Mapper.CreateMap<SourceType, DestinationType>().IgnoreAllNonExisting();
Также можно настроить этот метод в соответствии с вашими потребностями, например, игнорируя свойства, которые имеют защищенный или закрытый сеттер.