Исключить свойство при обновлении в Entity Framework
Я искал правильный способ пометить свойство, которое не будет изменено при обновлении модели в MVC.
например, давайте возьмем эту небольшую модель:
class Model
{
[Key]
public Guid Id {get; set;}
public Guid Token {get; set;}
//... lots of properties here ...
}
затем метод редактирования MVC создает выглядит следующим образом:
[HttpPost]
public ActionResult Edit(Model model)
{
if (ModelState.IsValid)
{
db.Entry(model).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
Теперь, если мое представление не содержит токен, он будет аннулирован через это редактирование.
Я ищу что-то вроде этого:
db.Entry(model).State = EntityState.Modified;
db.Entry(model).Property(x => x.Token).State = PropertyState.Unmodified;
db.SaveChanges();
лучший способ я нашел, чтобы быть включено и установить все свойства я хочу включить вручную, но я действительно только хочу сказать, какие из них должны быть исключены.
4 ответа:
мы можем использовать такой
db.Entry(model).State = EntityState.Modified; db.Entry(model).Property(x => x.Token).IsModified = false; db.SaveChanges();
он будет обновляться, но без свойства токена
создать новую модель, которая будет иметь ограниченный набор свойств, которые вы хотите обновить.
т. е. если ваша модель сущности:
public class User { public int Id {get;set;} public string Name {get;set;} public bool Enabled {get;set;} }
вы можете создать пользовательскую модель представления, которая позволит пользователю изменить имя, но не включен флаг:
public class UserProfileModel { public int Id {get;set;} public string Name {get;set;} }
когда вы хотите сделать обновление базы данных, вы делаете следующее:
YourUpdateMethod(UserProfileModel model) { using(YourContext ctx = new YourContext()) { User user = new User { Id = model.Id } ; /// stub model, only has Id ctx.Users.Attach(user); /// track your stub model ctx.Entry(user).CurrentValues.SetValues(model); /// reflection ctx.SaveChanges(); } }
при вызове этого метода вы обновите имя, но включенное свойство останется неизменным. Я использовал простые модели, но я думаю, вы получите картину, как его использовать.
Я думаю, вы не хотите, чтобы свойство было изменено только в некоторых случаях, потому что если вы не собираетесь использовать его никогда в своем приложении, просто удалите его из своей модели.
Если вы хотите использовать его только в некоторых сценариях и избежать его "обнуления" в приведенном выше случае, вы можете попробовать:
скрыть параметр в представлении с помощью HiddenFor:
@Html.HiddenFor(m => m.Token)
это сделает ваше исходное значение будет оставалось неизменным и передавалось обратно контроллеру.
- использовать
TryUpdateModel
: http://msdn.microsoft.com/en-us/library/dd460189 (v=vs.108). aspxзагрузите снова свой объект в контроллер из вашего
DBSet
и запустите этот метод. Вы можете указать белый список и черный список параметров, которые должны или не должны обновить.
Я сделал простой способ редактирования свойств объектов я поделюсь с вами. этот код будет редактировать имя и семейство свойств сущности:
public void EditProfileInfo(ProfileInfo profileInfo) { using (var context = new TestContext()) { context.EditEntity(profileInfo, TypeOfEditEntityProperty.Take, nameof(profileInfo.Name), nameof(profileInfo.Family)); } }
и этот код будет игнорировать для редактирования свойств имени и семейства сущности, и он будет редактировать другие свойства:
public void EditProfileInfo(ProfileInfo profileInfo) { using (var context = new TestContext()) { context.EditEntity(profileInfo, TypeOfEditEntityProperty.Ignore, nameof(profileInfo.Name), nameof(profileInfo.Family)); } }
использовать это расширение:
public static void EditEntity<TEntity>(this DbContext context, TEntity entity, TypeOfEditEntityProperty typeOfEditEntityProperty, params string[] properties) where TEntity : class { var find = context.Set<TEntity>().Find(entity.GetType().GetProperty("Id").GetValue(entity, null)); if (find == null) throw new Exception("id not found in database"); if (typeOfEditEntityProperty == TypeOfEditEntityProperty.Ignore) { foreach (var item in entity.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.GetProperty)) { if (!item.CanRead || !item.CanWrite) continue; if (properties.Contains(item.Name)) continue; item.SetValue(find, item.GetValue(entity, null), null); } } else if (typeOfEditEntityProperty == TypeOfEditEntityProperty.Take) { foreach (var item in entity.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.GetProperty)) { if (!item.CanRead || !item.CanWrite) continue; if (!properties.Contains(item.Name)) continue; item.SetValue(find, item.GetValue(entity, null), null); } } else { foreach (var item in entity.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.GetProperty)) { if (!item.CanRead || !item.CanWrite) continue; item.SetValue(find, item.GetValue(entity, null), null); } } context.SaveChanges(); } public enum TypeOfEditEntityProperty { Ignore, Take }