2012-04-21 15 views
29

Necesito actualizar todos los campos excepto property1 y property2 para el objeto de entidad dado.
Tener este código:Cómo actualizar no todos los campos de un objeto usando Entity Framework y EntityState.Modified

[HttpPost] 
    public ActionResult Add(object obj) 
    { 
     if (ModelState.IsValid) 
     { 
       context.Entry(obj).State = System.Data.EntityState.Modified; 

       context.SaveChanges();    
     } 
     return View(obj); 
    } 

cómo cambiarlo para agregar una excepción a obj.property1 y obj.property2 por no estar actualizada con este código?

Respuesta

57

Vamos a suponer que usted tiene una colección de las propiedades que deben excluirse:

var excluded = new[] { "property1", "property2" }; 

Con EF5 en .NET 4.5 se puede hacer esto:

var entry = context.Entry(obj); 
entry.State = EntityState.Modified; 
foreach (var name in excluded) 
{ 
    entry.Property(name).IsModified = false; 
} 

Esto utiliza una nueva característica de EF5 en .NET 4.5 que permite que una propiedad se configure como no modificada incluso después de haber sido configurada previamente para ser modificada.

Al utilizar EF 4.3.1 o EF5 en .NET 4 se puede hacer esto en su lugar:

var entry = context.Entry(obj); 
foreach (var name in entry.CurrentValues.PropertyNames.Except(excluded)) 
{ 
    entry.Property(name).IsModified = true; 
} 
+1

¡Buena mejora en .NET 4.5, gracias! – Slauma

+0

Sí. Esa es una gran implementación de eso en .Net 4.5 – mohamadreza

+0

Sé que esto está implícito, pero solo quería decir explícitamente que para EF 4.3.1 - no puede establecer entry.Property (...). IsModified = false; - Compilará, pero obtendrá un error de tiempo de ejecución al intentar hacer esto. Por lo tanto, creo que es conveniente decir que para EF 4.3.1 debe usar solo los positivos, en otras palabras: solo puede marcar cosas como modificadas (verdaderas) porque ya están configuradas como no modificadas (falsas). EF 5 le permite establecer libremente verdadero/falso; – dyslexicanaboko

19

No se puede definir tal excepción. Sin embargo, puede marcar propiedades individuales modificado:

context.Entry(obj).Property(o => o.Property3).IsModified = true; 
context.Entry(obj).Property(o => o.Property4).IsModified = true; 
// etc. 

Tenga en cuenta que no se admite la configuración IsModified a false una vez que haya marcado el estado de toda la entidad a Modified.

Para su finalidad realidad preferiría para cargar la entidad de la base de datos y luego actualizarlo mediante cambio normal de seguimiento:

var objInDB = context.Objects.Single(o => o.Id == obj.Id); 

obj.Property1 = objInDB.Property1; 
obj.Property2 = objInDB.Property2; 

context.Entry(objInDB).CurrentValues.SetValues(obj); 

context.SaveChanges(); 
+1

Me gusta su segundo bloque de código que es una solución agradable inversa de no utilizar falsa declaración. – mohamadreza

+1

+1 para lo siguiente: "Tenga en cuenta que establecer IsModified en falso no se admite una vez que haya marcado el estado de toda la entidad en Modificado." –

+0

Noté una nota similar aquí: https://msdn.microsoft.com/en-us/library/jj592677(v=vs.113).aspx que dice "Actualmente no es posible restablecer una propiedad individual para que no sea modificado después de haber sido marcado como modificado. Esto es algo que planeamos apoyar en una versión futura ". Sin embargo, funcionó cuando lo probé. Tal vez esa página msdn está desactualizada, aunque dice que fue actualizada el 23 de octubre de 2016. – KevinVictor

9

Esta cuestión ya fue muy bien contestadas, pero quería proporcionar un método de extensión para cualquier persona que le gustaría usarlo

Este código fue desarrollado para EF 4.3.1

//You will need to import/use these namespaces  
using System.Data.Entity; 
using System.Data.Entity.Infrastructure;  

//Update an entity object's specified columns, comma separated 
//This method assumes you already have a context open/initialized 
public static void Update<T>(this DbContext context, T entityObject, params string[] properties) where T : class 
{ 
    context.Set<T>().Attach(entityObject); 

    var entry = context.Entry(entityObject); 

    foreach(string name in properties) 
     entry.Property(name).IsModified = true; 

    context.SaveChanges(); 
} 

de uso Ejemplo de

using (FooEntities context = new FooEntities()) 
{ 
    FooEntity ef = new FooEntity(); 

    //For argument's sake say this entity has 4 columns: 
    // FooID (PK), BarID (FK), Name, Age, CreatedBy, CreatedOn 

    //Mock changes 
    ef.FooID = 1; 
    ef.Name = "Billy"; 
    ef.Age = 85; 

    context.Update<FooEntity>(ef, "Name", "Age"); //I only want to update Name and Age 
} 
0

Las respuestas anteriores (la mayoría de ellos) el uso DbContext. Para aquellos que usan ObjectContext estas soluciones no son accesibles.

Aquí es solución para ObjectContext estrictamente (EF5 .NET 4.5):

ctx.AddObject("ENTITYNAME", item); 
ctx.ObjectStateManager.ChangeObjectState(item, EntityState.Modified); 

var entry = ctx.ObjectStateManager.GetObjectStateEntry(item); 
entry.RejectPropertyChanges("PROPERTY_TO_EXCLUDE"); 
Cuestiones relacionadas