He estado buscando una forma adecuada de marcar una propiedad para que NO se cambie 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 que crea MVC 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á mediante 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 ser inclusivo y establecer todas las propiedades que quiero incluir a mano, pero en realidad solo quiero decir cuáles excluir.
c#
asp.net-mvc
entity-framework
Manuel Schweigert
fuente
fuente
using (var db2 = new DataContext()) model.Token = db2.Models.Find(model.Id).Token;
Pero tampoco estoy contento con esta.Respuestas:
podemos usar así
db.Entry(model).State = EntityState.Modified; db.Entry(model).Property(x => x.Token).IsModified = false; db.SaveChanges();
se actualizará pero sin la propiedad Token
fuente
AddOrUpdate
? - ¿Cómo sabes usarEntityState.Modified
oEntityState.Added
?db.Entry(model).State = EntityState.Modified;
después de configurardb.Entry(model).Property(x => x.Token).IsModified = false;
, la propiedad se actualizará al guardar.Cree un nuevo modelo que tendrá un conjunto limitado de propiedades que desea 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 permitirá al usuario cambiar el nombre, pero no la marca habilitada:
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 Enabled permanecerá sin cambios. Usé modelos simples, pero creo que te darás una idea de cómo usarlo.
fuente
Cualquiera que busque cómo lograr esto en EF Core. Es básicamente lo mismo, pero su IsModified debe ser después de agregar el modelo que se actualizará.
db.Update(model); db.Entry(model).Property(x => x.Token).IsModified = false; db.SaveChanges();
fuente
Creé una manera fácil de editar propiedades de entidades que compartiré contigo. este código editará las propiedades de Nombre y 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 se 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)); } }
Utilice esta extensión:
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 }
fuente
Supongo que no desea que se cambie la propiedad solo en algunos casos, porque si no la va a usar 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 modificar y se devuelva al controlador.
TryUpdateModel
: http://msdn.microsoft.com/en-us/library/dd460189(v=vs.108).aspxCargue 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 se actualizarán o no.fuente
@Html.HiddenFor
escribirá el valor en el HTML de la vista y permitirá al usuario usar el elemento de inspección dentro de su navegador y modificarlo. Después de hacer eso, todavía se pasa al controlador pero con un valor diferente y se actualizará. Lo acabo de probar.