2

Проблема возникает, когда я хочу сохранить объект, отправленный обратно из формы, но исключая конкретное поле из результирующего оператора 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(); 

Есть ли лучшее решение этой проблемы, как использование фиктивного значения, как описано выше, кажется, как-то вроде хака?

+2

Вы думаете об использовании ViewModels и уменьшении количества ненужных данных, которые вы перемещаете? –

+0

Обычно мы используем подход viewmodel, но в этом случае мы приняли решение разоблачить наши модели db на уровне презентации, чтобы мы могли полностью использовать функции лесов/шаблонов в vs2015, используя первый подход db. Преимущество этого заключалось в том, чтобы удалить весь код viewmodel и mapping, связанный с кодом (automapper и т. Д.), Который был очень полезен в упрощении нашего кода. У нас были проблемы в прошлом, когда бизнес-логика была помещена в виде отображения модели. Компромисс заключается в том, что мы должны обеспечить жесткий контроль над изменениями db/rescaffolding, поскольку мы сознаем введение жесткой связи. – Richard

ответ

0

GO с хранимой процедурой подходом, где вам не нужно беспокоиться о рамках сущности, вызов хранимой процедуры из рамок сущности и обновить таблицу внутри SQL заявления без обновления поля пароля

1

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

Вы можете использовать ViewModel для привязки к своей веб-странице и только поставлять поля, которые необходимы (так что в вашем случае, а не поле пароля). Когда пользователь возвращает данные POST, вы можете загрузить пользователя из db, установить только те поля, которые вам нужны, а затем сохранить данные обратно. Поле пароля не изменится.

Например, предположим, таблицу пользователя заключается в следующем:

ID 
UserName 
Password 
FullName 

Вы бы вид модели класса

public class UserViewModel 
{ 
    public int ID { get; set; } 
    public string UserName { get; set; } 
    public string FullName { get; set; } 
} 

Когда данные размещены на сервер от клиента:

using (MyEntity db = new MyEntity()) 
{ 
    User u = db.Users.Find(userViewModel.ID); 
    u.UserName = userViewModel.UserName; 
    u.FullName = userViewModel.FullName; 
    db.SaveChanges(); 
} 
+0

Обычно мы используем подход viewmodel, но в этом случае мы приняли решение разоблачить наши модели db на уровне презентации, чтобы мы могли полностью использовать функции лесов/шаблонов в vs2015, используя первый подход db. Преимущество этого заключалось в том, чтобы удалить весь код viewmodel и mapping, связанный с кодом (automapper и т. Д.), Который был очень полезен в упрощении нашего кода. У нас были проблемы в прошлом, когда бизнес-логика была помещена в виде отображения модели. Компромисс заключается в том, что мы должны обеспечить жесткий контроль над изменениями db/rescaffolding, поскольку мы сознаем введение жесткой связи. – Richard

Смежные вопросы