как использовать автомапер в методе редактирования. net core mvc - PullRequest
0 голосов
/ 22 января 2020

В моем текущем. net core mvc проекте с каркасом сущностей я использую Autopper с DI. В моем методе редактирования мне нужно обновить модель домена, используя viewmodel. Это где я использую Autopper. Но viewmodel содержит только несколько свойств domainmodel. Другие свойства должны быть сохранены, однако они устанавливаются в ноль или по умолчанию, когда я применяю _context.Update(modelToSubmit); Как я могу обновить только те поля в модели домена, которые я на самом деле хочу изменить (те, которые находятся в модели представления)?

В настоящее время это делается в этом проекте путем добавления всех свойств в viewmodel и использования тега @Html.HiddenFor в представлении, что я считаю плохой практикой и от которого я хочу избавиться.

У меня есть одна строка кода для сопоставления:

DomainModel model = _mapper.Map<DomainModel>(viewModel);

Редактировать: У меня сейчас (на основе ответа ниже):

DatabaseModel originalRecord = _unitOfWork.DatabaseModel.Get(id);
var mappedModel = _mapper.Map<ViewModel>(originalRecord);

var newDto = _mapper.Map<ViewModel, DataBaseModel>(returnedViewModel, originalRecord);

originalRecord = _mapper.Map<ViewModel, DatabaseModel>(mappedModel);
_unitOfWork.DatabaseModel.Update(originalRecord);

Мой файл сопоставления:

CreateMap<ViewModel, DatabaseModel>()
            .IgnoreAllPropertiesWithAnInaccessibleSetter()
            .ForPath(dest => dest.ID, opt => opt.Ignore())
            .ForPath(dest => dest.Deadline, opt => opt.Ignore())
            .ForPath(dest => dest.RecordCreated, opt => opt.Ignore())
        .ForPath(dest => dest.Status, opt => opt.Ignore())
        .ReverseMap();

Когда я сохраняю модель на веб-сайте, я получаю эту ошибку:

Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: ожидается, что операция базы данных повлияет на 1 ряд (ы), но фактически затронули 0 ряд (а).

Запрос на получение originalRecord имеет метод AsNoTracking(), но он все равно выдает эту ошибку.

1 Ответ

1 голос
/ 22 января 2020

Сначала вам нужно создать ViewModel, которая имеет только те свойства, которые пользователь может изменить. Затем вы должны настроить свой преобразователь так, чтобы он игнорировал несуществующие свойства в источнике.

configuration.CreateMap<MyViewModel, MyModel>()
                        .IgnoreAllPropertiesWithAnInaccessibleSetter()
                        .ForPath(s => s.Unmapped, opt => opt.Ignore())
                        .ForPath(s => s.Id, opt => opt.Ignore())
                        .ReverseMap();

В приведенном выше примере я использую .Ignore () для свойства Id, потому что EnityFramework не примет ваше SaveChanges() если вы измените значение первичного ключа. Даже если оно было изменено с тем же значением.

Также, когда вы используете _mapper.Map<DomainModel>(viewModel);, вы создаете совершенно новый целевой объект, и все свойства, которые не существуют - исходный объект будет нулевым или по умолчанию .

Вы должны использовать

model = _mapper.Map<MyViewModel, MyModel>(viewModel, model);

Вы видите пример в этом. net fiddle: https://dotnetfiddle.net/oyFupE

И это ссылка может дать вам больше информации о игнорировании свойств в AutoMapper: https://dotnettutorials.net/lesson/ignore-using-automapper-in-csharp/

EDIT : в новом коде, который вы добавили в свой код, у вас больше кода, чем нужно вопрос. Как у вас уже есть ViewModel и получить модель из базы данных. Теперь вам нужно вызывать automapper только один раз.

public void Update(ViewModel returnedViewModel)
{
    // Gets the orininal Model from DataBase.
    DatabaseModel originalRecord = _unitOfWork.DatabaseModel.Get(id);

    // Merge original model with the ViewModel   
    originalRecord = _mapper.Map<ViewModel, DatabaseModel>(mappedModel, originalRecord);

    // SaveChanges
    _unitOfWork.DatabaseModel.Update(originalRecord);
}

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

...