Проблема возникает, когда я хочу сохранить объект, отправленный обратно из формы, но исключая конкретное поле из результирующего оператора SQL. В этом случае я не хотел включать поле пароля в форму редактирования пользователя.Исключение немодифицированного поля при выполнении SaveChanges
Способ управления редактирования HttpPost содержал следующее:
db.Users.Attach(user);
db.Entry(user).State = EntityState.Modified;
db.Entry(user).Property(x => x.Password).IsModified = false;
db.SaveChanges();
Я предположил, что заявление .IsModified будет означать, что сгенерированный SQL будет состоять из оператора UPDATE без поля ввода пароля и поэтому не перезаписывать существующие значения пароля с нулевым значением в базе данных.
Однако это было не так, и EF, похоже, работает несколько иначе. Мой класс пользователя и его ассоциированный класс метаданных не указывали, что поле пароля было необходимо, и все же при выполнении было вызвано поле «Пароль», которое было вызвано DbEntityValidationException при вызове SaveChanges.
Одним из решений было бы включить поле пароля с его значением в виде скрытого поля формы, которого было бы достаточно в большинстве случаев, но в этом случае это не было бы хорошей идеей в качестве пароля, хэширования или каких-либо других данных.
При дальнейшей проверке казалось, что в этом случае, когда мы используем первый подход к базе данных, файл .edmx содержит директиву «не нуль» в поле «Пароль». Когда EF приходит для выполнения фактического сохранения, это проверяется и возникает исключение.
Это было не совсем интуитивно, по моему мнению, но как только оно известно, его можно обойти.
Моим решением было предоставить значение для исключенного поля и сохранить инструкцию .IsModified. Это означает, что исключение DbEntityValidationException не генерируется, поскольку EF видит поле Password, содержащее значение (как указано в файле .edmx), но на самом деле не записывается в базу данных из-за того, что IsModified является ложным. Например.
user.Password = "not required";
db.Users.Attach(user);
db.Entry(user).State = EntityState.Modified;
db.Entry(user).Property(x => x.Password).IsModified = false;
db.SaveChanges();
Есть ли лучшее решение этой проблемы, как использование фиктивного значения, как описано выше, кажется, как-то вроде хака?
Вы думаете об использовании ViewModels и уменьшении количества ненужных данных, которые вы перемещаете? –
Обычно мы используем подход viewmodel, но в этом случае мы приняли решение разоблачить наши модели db на уровне презентации, чтобы мы могли полностью использовать функции лесов/шаблонов в vs2015, используя первый подход db. Преимущество этого заключалось в том, чтобы удалить весь код viewmodel и mapping, связанный с кодом (automapper и т. Д.), Который был очень полезен в упрощении нашего кода. У нас были проблемы в прошлом, когда бизнес-логика была помещена в виде отображения модели. Компромисс заключается в том, что мы должны обеспечить жесткий контроль над изменениями db/rescaffolding, поскольку мы сознаем введение жесткой связи. – Richard