2009-02-02 12 views
39

Estoy bastante seguro de haber visto la respuesta a esta pregunta en algún lugar, pero como no pude encontrar con un par de búsquedas en SO o Google, la vuelvo a preguntar ...¿Cómo elimino un objeto de un modelo de Entity Framework sin cargarlo primero?

En Entity Framework , la única manera de eliminar un objeto de datos parece ser

MyEntityModel ent = new MyEntityModel(); 
ent.DeleteObject(theObjectToDelete); 
ent.SaveChanges(); 

Sin embargo, este enfoque requiere que el objeto que se va a cargar, en este caso, el controlador primero, sólo para eliminarlo. ¿Hay alguna manera de eliminar un objeto comercial haciendo referencia solo a su ID, por ejemplo?

Si hay una forma más inteligente de usar expresiones Linq o Lambda, también está bien. El objetivo principal, sin embargo, es evitar cargar datos solo para eliminarlos.

+2

hay una manera de hacerlo esto agradable y genéricamente: http://j.mp/f0x0Bh – BritishDeveloper

+0

@BritishDeveloper: ¡Interesante! Sin embargo, después de haber formulado esta pregunta me di cuenta de que a menudo hay una buena causa para recuperar la entidad primero, al menos si hay relaciones clave foráneas involucradas. –

+0

Posible duplicado de [Cómo eliminar un objeto por id. Con entidad de marco] (http://stackoverflow.com/questions/2471433/how-to-delete-an-object-by-id-with-entity-framework) –

Respuesta

19

Vale la pena saber que el Entity Framework es compatible tanto con LINQ a Entidades y Entity SQL. Si desea hacer eliminaciones o actualizaciones que podrían afectar muchos registros, puede usar el equivalente de ExecuteNonQuery.

En Entity SQL ejemplo de esta situación

Using db As New HelloEfEntities 

     Dim qStr = "Delete " & _ 
        "FROM Employee" 
     db.ExecuteStoreCommand(qStr) 
     db.SaveChanges() 
    End Using 

En este ejemplo, db es mi ObjectContext. También tenga en cuenta que la función ExecuteStoreCommand toma una matriz opcional de parámetros.

+2

Esta respuesta va directamente al punto de lo que el autor de la pregunta desea hacer y debe marcarse como la respuesta aceptada. Otras soluciones como construir entidad desde la nada son menos óptimas. También mira esto http://msdn.microsoft.com/en-us/library/ee358769.aspx – mare

+17

¿Por qué llamas a SaveChanges después del ExecuteStoreCommand? – epotter

+7

¡Cuerda mágica! Ugh. – mayu

8

Encontré this post, que indica que realmente no hay mejor manera de eliminar registros. La explicación dada fue que todas las claves externas, relaciones, etc. que son únicas para este registro también se eliminan, por lo que EF necesita tener la información correcta sobre el registro. Estoy desconcertado por qué esto no podría lograrse sin cargar datos de un lado a otro, pero como no va a suceder muy a menudo, he decidido (por ahora) que no me molestaré.

Si usted tiene una solución a este problema, no dude en hacérmelo saber =)

+3

¿Qué le parece usar un procedimiento almacenado? –

4

Disculpas de antemano, pero tengo que cuestionar su objetivo.

Si elimina un objeto sin leerlo nunca, no podrá saber si otro usuario ha cambiado el objeto entre la fecha en que confirmó que deseaba eliminar el objeto y la eliminación real. En la "vieja SQL normal", esto sería como hacerlo:

DELETE FROM FOO 
WHERE ID = 1234 

Por supuesto, la mayoría de la gente en realidad no hacen esto. En su lugar, hacer algo como:

DELETE FROM FOO 
WHERE ID = 1234 
    AND NAME = ?ExpectedName AND... 

El punto es que la eliminación falle (no hacer nada) si otro usuario ha cambiado el registro en el ínterin.

Con esto, una mejor declaración del problema, hay dos soluciones posibles al usar Entity Framework.

  1. En su método Eliminar, la instancia existente, compare los valores esperados de las propiedades y elimine si son iguales. En este caso, Entity Framework se encargará de escribir una declaración DELETE que incluye los valores de las propiedades.

  2. Escriba un procedimiento almacenado que acepte tanto el IDE como los otros valores de propiedad y ejecútelo.

+1

Es un objetivo perfectamente válido si sus objetos nunca se modifican durante su vida útil y/o su consulta para ENCONTRAR los objetos para eliminar implica que todas las propiedades que estaría verificando ya están en el valor correcto de todos modos. –

4

Hay una manera de burlar cargar una entidad por la re-cálculo es EntityKey. Parece un truco, pero podría ser la única forma de hacerlo en EF.

Blog artículo sobre Deleting without Fetching

3
var toDelete = new MyEntityModel{ 
    GUID = guid, 
    //or ID = id, depending on the key 
    }; 
Db.MyEntityModels.Attach(toDelete); 
Db.MyEntityModels.DeleteObject(toDelete); 
Db.SaveChanges(); 

En caso de que su clave contiene varias columnas, es necesario proporcionar todos los valores (por ejemplo, GUID, Columnx, columnY etc).

También eche un vistazo a here para una función genérica si le apetece algo elegante.

+0

Esta es la mejor manera (lo llamo usando un objeto marcador de posición) pero sufre las mismas preocupaciones de concurrencia traídas por Stuntz a continuación. – dansan

3

Con Entity Framework 5 hay Entity Framework Extended Library. Disponible en NuGet. A continuación, puede escribir algo como:

context.Users.Delete(u => u.Id == id); 

También es útil para eliminaciones masivas.

+0

¡Esta es una increíble biblioteca! Gracias –

4

Puede crear un objeto con el mismo ID y pasarla a través de la eliminación pero es bueno para los objetos simples si tiene relaciones complejas que puede necesitar más que eso

   var user = new User { ID = 15 }; 
       context.Entry(user).State = EntityState.Deleted; 
       context.SaveChanges(); 
Cuestiones relacionadas