Excluir propiedad en la actualización en Entity Framework

He estado buscando una manera adecuada de marcar una propiedad para que NO se modifique al actualizar un modelo en MVC.

Por ejemplo, tomemos este pequeño modelo:

class Model { [Key] public Guid Id {get; set;} public Guid Token {get; set;} //... lots of properties here ... } 

entonces el método de edición MVC crea se ve así:

 [HttpPost] public ActionResult Edit(Model model) { if (ModelState.IsValid) { db.Entry(model).State = EntityState.Modified; db.SaveChanges(); return RedirectToAction("Index"); } return View(model); } 

ahora si mi vista no contiene el token, se anulará a través de esa edición.

Estoy buscando algo como esto:

 db.Entry(model).State = EntityState.Modified; db.Entry(model).Property(x => x.Token).State = PropertyState.Unmodified; db.SaveChanges(); 

La mejor manera que he encontrado hasta ahora es incluirme y establecer todas las propiedades que quiero incluir a mano, pero realmente solo quiero decir cuáles quedarán excluidas.

podemos usar así

  db.Entry(model).State = EntityState.Modified; db.Entry(model).Property(x => x.Token).IsModified = false; db.SaveChanges(); 

se actualizará pero sin propiedad Token

Crea un nuevo modelo que tendrá un conjunto limitado de propiedades que deseas actualizar.

Es decir, si su modelo de entidad es:

 public class User { public int Id {get;set;} public string Name {get;set;} public bool Enabled {get;set;} } 

Puede crear un modelo de vista personalizado que permita al usuario cambiar el nombre, pero no el indicador Habilitado:

 public class UserProfileModel { public int Id {get;set;} public string Name {get;set;} } 

Cuando desee actualizar la base de datos, haga lo siguiente:

 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(); } } 

Cuando llame a este método, actualizará el Nombre, pero la propiedad Habilitada permanecerá sin cambios. Usé modelos simples, pero creo que obtendrás la imagen de cómo usarlo.

Supongo que no desea que la propiedad se cambie solo en algunos casos, porque si no va a utilizarla nunca en su aplicación, simplemente elimínela de su modelo.

En caso de que quiera usarlo solo en algunos escenarios y evitar su “anulación” en el caso anterior, puede intentar:

  • Ocultar el parámetro en la vista con HiddenFor:

    @Html.HiddenFor(m => m.Token)

Esto hará que su valor original se mantenga sin modificaciones y se devuelva al controlador.

Cargue nuevamente su objeto en el controlador desde su DBSet y ejecute este método. Puede especificar tanto una lista blanca como una lista negra de parámetros que deberán o no actualizarse.

Hice una manera fácil de editar las propiedades de las entidades que compartiré contigo. este código editará Nombre y Propiedades de la familia de la entidad:

  public void EditProfileInfo(ProfileInfo profileInfo) { using (var context = new TestContext()) { context.EditEntity(profileInfo, TypeOfEditEntityProperty.Take, nameof(profileInfo.Name), nameof(profileInfo.Family)); } } 

Y este código ignorará para editar las propiedades de Nombre y Familia de la entidad y editará otras propiedades:

  public void EditProfileInfo(ProfileInfo profileInfo) { using (var context = new TestContext()) { context.EditEntity(profileInfo, TypeOfEditEntityProperty.Ignore, nameof(profileInfo.Name), nameof(profileInfo.Family)); } } 

Use esta extensión:

 public static void EditEntity(this DbContext context, TEntity entity, TypeOfEditEntityProperty typeOfEditEntityProperty, params string[] properties) where TEntity : class { var find = context.Set().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 }