2011-06-22 22 views
5

Tengo un escenario donde tengo que actualizar una entidad si existe o agregar una nueva si no existe.Entidad Marco: actualizar entidad o agregar si no existe

Me gustaría ejecutar un único método para esto (sería genial si fuera un solo viaje al servidor).

¿Hay algo así en EF?

Ahora mismo mi código es el siguiente:

var entity = db.Entities.FirstOrDefault(e => e.Id == myId); 
if (entity == null) 
{ 
    entity = db.Entities.CreateObject(); 
    entity.Id = myId; 
} 

entity.Value = "my modified value"; 

db.SaveChanges(); 

Pero me gustaría evitar la primera consulta, algo como esto:

var entity = new Entity(); 
entity.Id = myId; 
entity.Value = "my modified value"; 
db.AddOrAttach(entity); 
db.SaveChanges(); 

¿Hay algo similar? o tengo que realizar la primera consulta sin importar nada?

Gracias

+0

Eche un vistazo a mi pregunta sobre cómo hacer un guardado genérico con EF: http://stackoverflow.com/questions/6018711/generic-way-to-check-if-entity-exists-in-entity-framework resultado de que era escribir un método de guardado genérico (insertar o actualizar según se requiera). Rápidamente se vuelve desordenado. – Yuck

Respuesta

2

tiene que realizar la primera consulta no importa lo que, por desgracia.

Una opción sería escribir un procedimiento almacenado que realice un T-SQL MERGE luego asignarlo a una importación de función, aunque eso requeriría que pase los valores escalares de la entidad como parámetros (y el soporte para las propiedades de navegación hacerse), pero lograría lo que estás buscando.

+0

Eso sería demasiado trabajo para cada mesa donde tengo este problema. Quizás lo haga si esto se convierte en un problema de rendimiento. – willvv

0

Me corrió un cierto código de prueba rápida para edición en MVC 3 con EF 4 y parece que funciona para editar con siguiente código:

using (var context = new TestStackOverFlowEntities()) 
{ 
    Person p = new Person(); 
    p.Id = long.Parse(collection["Id"]); 
    p.FirstName = collection["FirstName"]; 
    p.LastName = collection["LastName"]; 
    context.People.Attach(p); 
    context.ObjectStateManager.ChangeObjectState(p, System.Data.EntityState.Modified); 
    context.SaveChanges(); 
    return RedirectToAction("Index"); 
} 

Editar: he comprobado con la creación de nuevo objeto también, que necesita para cambiar esta

context.ObjectStateManager.ChangeObjectState(p, System.Data.EntityState.Added); 

cuando Id == 0 // es decir, nuevo objeto.

Código rápido y sucio para agregar nueva es la siguiente:

using (var context = new TestStackOverFlowEntities()) 
{ 
    Person p = new Person();       
    p.Id = 0; 
    p.FirstName = collection["FirstName"]; 
    p.LastName = collection["LastName"]; 
    context.People.Attach(p); 
    context.ObjectStateManager.ChangeObjectState(p, System.Data.EntityState.Added); 
    context.SaveChanges(); 
    return RedirectToAction("Index"); 
} 
+1

No se está enfocando en la pregunta principal. Su respuesta asume que sé si quiero actualizar o insertar. La idea de la pregunta es que no sé lo que debería suceder. – willvv

+0

"Tengo un escenario donde tengo que actualizar una entidad si existe o agregar una nueva si no existe". - La muestra que te dí maneja eso, pero la suposición que hice es la entidad. Sería 0 para los recién agregados y> 0 para los existentes. Eso no funcionará para algo así como un GUID. –

+1

Sí, pero en mi caso el elemento que estoy agregando tiene una clave externa como clave primaria compuesta, por lo tanto, nunca será cero. Si tuviera el cero, podría usarlo en lugar de la primera consulta de mi código. – willvv

0

Si usted está tratando de limitar el código para aclarar sus controladores:

db.Attach(model); 
db.SaveChanges(model); 

se actualizará si existe la clave de entidad, y crear si no lo hace.

+0

Por supuesto, todavía hay dos consultas. – shannon

Cuestiones relacionadas