Автоматизатор, использующий HasDefaultValueSql

#c# #automapper #.net-core-2.2

#c# #автоматизатор #.net-core-2.2

Вопрос:

В моем проекте Entity Framework Core 2.2 API я создал контекст. Поскольку он представляет данные из моей базы данных, я получаю записи типа —

 entity.Property(e => e.Active)
    .IsRequired()
    .HasDefaultValueSql("((1))");
  

где Active требуется значение по умолчанию 1.

Я также сопоставляю объекты с помощью AutoMapper.

Мой класс MappingEntity —

 public class MappingEntity : Profile
{
    public MappingEntity()
    {
        CreateMap<MemberUpdate, Member>();
    }
}
  

который сопоставит ViewModel MemberUpdate с моим объектом базы данных Member

Кажется, я теряю значение по умолчанию в своем контроллере —

 public ActionResult Account(int id, [FromBody]MemberUpdate updatedMember)
{
    Member member = _memberRepository.GetById(id);
    //HERE MY MEMBER OBJECT IS CORRECT AND `ACTIVE` HAS IT'S DEFAULT VALUE

    member = _mapper.Map<Member>(updatedMember);
    //HERE MY MEMBER OBJECT IS INCORRECT AND THE ACTIVE FIELD DOES NOT SHOW THE DEFAULT VALUE

    //proceed to save back to the database
}
  

Существует ли настройка AutoMapper для сохранения значения по умолчанию?

Ответ №1:

AutoMapper не может сохранить ваше значение по умолчанию, потому что он даже не знает, что оно существует.

.HasDefaultValueSql("((1))"); Это параметр, который EntityFramework использует, когда он создает объект, но в этом случае AutoMapper создает объект, поэтому информация теряется.

Однако, что вы могли бы сделать, это применить некоторую пользовательскую логику к вашему отображению, чтобы впоследствии добавить значение по умолчанию. Это выглядело бы примерно следующим образом:

 CreateMap<MemberUpdate, Member>()
    .AfterMap((memberUpdate, member) =>
         member.Active = memberUpdate.Active == default(int) ? 1 : memberUpdate.Active); 
  

Это просто выполняет сопоставление по умолчанию между Member и MemberUpdate , а затем впоследствии присваивает значение по умолчанию, которое вы хотите Member .

В качестве альтернативы, вы могли бы изменить свою модель, чтобы внутри нее было значение по умолчанию, вместо того, чтобы выполнять это назначение извне, например:

 public int Active { get; } = 1;
  

Хотя я сомневаюсь, что этот вариант будет вам полезен, поскольку вы хотите, чтобы EF справился с этим за вас. Я бы предложил где-нибудь преобразовать жестко закодированное 1 значение в константу, а затем использовать эту константу в вашем отображении AutoMapper и в настройках EF.

Надеюсь, это поможет.

Комментарии:

1. Возможно, я не совсем ясно выразился. Принудительно ли это сопоставление значения после сопоставления? Что, если входящая viewmodel устанавливает его на что-то другое?

2. Не видя ваших моделей, мне, к сожалению, пришлось сделать пару предположений. Одним из них было то, что ваша входящая модель на самом деле не имела такого свойства, но, похоже, я ошибался в этом. Можете ли вы сказать мне, каково ожидаемое поведение, когда входящая viewmodel имеет значение, по сравнению с тем, когда оно не имеет?

3. Когда входящая модель обладает этим свойством, сопоставьте ее. Если это свойство не было установлено для входящей модели, используйте базу данных по умолчанию

4. Хорошо, я только что отредактировал код сопоставления в своем сообщении, чтобы обработать этот вариант использования. Надеюсь, это поможет!