#c# #asp.net-mvc-3 #entity-framework #entity-framework-4 #entity-framework-4.1
#c# #asp.net-mvc-3 #entity-framework #entity-framework-4 #entity-framework-4.1
Вопрос:
Я использую Asp.net MVC и Entity framework (приведенный ниже код предназначен только для демонстрации)
У меня есть модель, подобная приведенной ниже
public class Person
{
[Key]
public int Id { get; set; }
[Required]
public string FirstName { get; set; }
/*Time at which person was created*/
public DateTime CreatedOn { get; set; } /*should not change once created*/
}
Во время создания вставки нового пользователя я вручную установил свойство CreatedOn datetime.
При обновлении
В моем представлении есть только одно текстовое поле
@using (Html.BeginForm())
{
@Html.LabelFor(a => a.FirstName)
@Html.EditorFor(a => a.FirstName)
@Html.ValidationMessageFor(a => a.FirstName)
<br />
<input type="submit" name="name" value="submit" />
}
Контроллер
[HttpPost]
public ActionResult EditPerson(Person person)
{
if (ModelState.IsValid)
{
db.Entry(person).State = EntityState.Modified;
db.SaveChanges();
/* ----------------
Error here
-----------------
*/
return RedirectToAction("ListPerson");
}
return View(person);
}
Я получаю сообщение об ошибке в указанной точке моего кода, ошибка: The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.
ошибка кажется очевидной, поскольку person
объект, полученный внутри контроллера, имеет значение времени по умолчанию, и entity Framework также пытается обновить это поле.
Мой вопрос в том, как я могу поручить entity Framework не обновлять свойство. Предположим, что в приведенном выше случае, если для CreatedOn
свойства я говорю entity framework не обновлять его, я не получу ошибку.
Я попробовал [Editable(false)]
включить атрибут CreatedOn
, но это не сработало.
Есть несколько вариантов, например, перед обновлением я сначала загружаю существующий объект из базы данных и копирую свойство CreatedOn…..
Я хочу, чтобы вы знали, что в моей реальной модели есть много свойств, которые я не хочу обновлять, и таких моделей много, поэтому я ожидаю реалистичных ответов.
Редактировать 1
Сначала я использую код.
Комментарии:
1. На данный момент не на моем компьютере, но делаю это из памяти. Я думаю, вы можете выбрать поле в своей модели сущности, а на вкладке «Свойства» выбрать «вычислено из сгенерированного в хранилище поля шаблона».
2. если я не ошибаюсь, то вычисленное значение будет меняться
CreatedOn
при каждом обновлении, также вы не увидите ошибку при попытке в памяти.
Ответ №1:
Конкретная ошибка, которую вы получаете, заключается в том, что для CreatedOn установлено значение по умолчанию. Когда вы выполняете обратную передачу, вам нужно будет загрузить объект из базы данных, обновить его, а затем сохранить. Делая это, вы остановите эту конкретную ошибку, с которой вы сталкиваетесь.
Похоже, что вы используете свою entity model в качестве модели в своем контроллере. Я бы не рекомендовал это. Создав модель специально для post, вы можете удалить все не редактируемые поля из своей модели. Затем вы скопировали бы значения модели из ViewModel в свою Entity model. Это не позволяет пользователям редактировать свойства, которые вы, возможно, не хотите, чтобы они редактировали.
public class PersonViewModel
{
[Key]
public int Id { get; set; }
[Required]
public string FirstName { get; set; }
}
Основная причина, по которой это хорошая идея, заключается в том, что кто-то может попытаться угадать, какие значения также могут работать. Например, если у вас было вызвано свойство вашего Person
объекта IsAdministrator
, и я должен был перехватить сообщение и добавить amp;IsAdministrator=onamp;Adminstrator=onamp;Admin=on
(чтобы охватить несколько баз), тогда ModelBinder примет это значение и применит его к модели. Теперь я только что стал администратором в вашей системе. Я понимаю, что это большая работа, если у вас много моделей, но никогда не рекомендуется использовать ваши модели сущностей для сообщений.
Вы также можете использовать Bind
атрибут для ограничения элементов, связанных с помощью mapper.
public ActionResult EditPerson([Bind(Exclude = "CreatedOn")] Person person)
Это должно помешать связующему связывать это конкретное свойство. Однако это не решит вашу проблему, поскольку при создании объекта person всегда устанавливается значение по умолчанию. Единственный способ исправить это — загрузить ваш объект из базы данных, а затем обновить / сохранить его.