Estoy eliminando varios elementos de una tabla usando Entity Framework. No hay una clave externa / objeto primario, así que no puedo manejar esto con OnDeleteCascade.
En este momento estoy haciendo esto:
var widgets = context.Widgets
.Where(w => w.WidgetId == widgetId);
foreach (Widget widget in widgets)
{
context.Widgets.DeleteObject(widget);
}
context.SaveChanges();
Funciona pero el foreach me molesta. Estoy usando EF4 pero no quiero ejecutar SQL. Solo quiero asegurarme de que no me falta nada, esto es tan bueno como se pone, ¿verdad? Puedo abstraerlo con un método de extensión o ayudante, pero en algún lugar todavía vamos a hacer un foreach, ¿verdad?
entity-framework
Jon Galloway
fuente
fuente
Respuestas:
Si no desea ejecutar SQL directamente, llamar a DeleteObject en un bucle es lo mejor que puede hacer hoy.
Sin embargo, puede ejecutar SQL y aún así hacerlo completamente general a través de un método de extensión, utilizando el enfoque que describo aquí .
Aunque esa respuesta fue para 3.5. Para 4.0 probablemente usaría la nueva API ExecuteStoreCommand debajo del capó, en lugar de desplegarme en StoreConnection.
fuente
EntityFramework 6 ha hecho esto un poco más fácil con
.RemoveRange()
.Ejemplo:
fuente
Bueno, sí, excepto que puedes convertirlo en dos líneas:
fuente
fuente
WHERE IN ({0})
, y entonces el segundo argumento debería serString.Join(",", idList)
.EntityFramework.Extended
String.Join
, es posible que necesite usarstring.Format
y pasar la cadena SQL ya formada al comando. Mientras su lista solo tenga números enteros, no hay riesgo de ataque de inyección. Verifique esta pregunta: ¿cómo puedo pasar una matriz a un comando de ejecutar tienda?Sé que es bastante tarde, pero en caso de que alguien necesite una solución simple, lo bueno es que también puede agregar la cláusula where con ella:
Nota: recién probado con MSSQL2008.
Actualizar:
La solución anterior no funcionará cuando EF genere una instrucción sql con parámetros , así que aquí está la actualización para EF5 :
Requiere un poco de reflexión pero funciona bien.
fuente
Para cualquiera que use EF5, se puede usar la siguiente biblioteca de extensiones: https://github.com/loresoft/EntityFramework.Extended
fuente
Delete()
función en mis entidades en EF6.context.Widgets.Where(w => w.WidgetId == widgetId).Delete();
es la forma más nueva con EntityFrameworkTodavía parece una locura tener que retirar algo del servidor solo para eliminarlo, pero al menos recuperar solo las ID es mucho más ágil que eliminar las entidades completas:
fuente
Widget
objetos de código auxiliar solo tienen unaId
propiedad inicializada . La forma de evitar esto es usarcontext.Configuration.ValidateOnSaveEnabled = false
(al menos en EF6). Esto deshabilita la validación propia de Entity Framework, pero todavía realiza la validación propia de la base de datos, por supuesto.delete
con una solución similar paraupdate
las entidades ing sin cargarlas.EF 6.1
Uso:
fuente
Para EF 4.1,
fuente
Puede usar bibliotecas de extensiones para hacer eso como EntityFramework.Extended o Z.EntityFramework.Plus.EF6, están disponibles para EF 5, 6 o Core. Estas bibliotecas tienen un gran rendimiento cuando tiene que eliminar o actualizar y usan LINQ. Ejemplo para eliminar ( fuente más ):
ctx.Users.Where(x => x.LastLoginDate < DateTime.Now.AddYears(-2)) .Delete();
o ( fuente extendida )
context.Users.Where(u => u.FirstName == "firstname") .Delete();
Estos usan sentencias SQL nativas, por lo que el rendimiento es excelente.
fuente
La forma más rápida de eliminar es usar un procedimiento almacenado. Prefiero procedimientos almacenados en un proyecto de base de datos sobre SQL dinámico porque los cambios de nombre se manejarán correctamente y tendrán errores de compilación. El SQL dinámico podría referirse a tablas que se han eliminado / renombrado causando errores de tiempo de ejecución.
En este ejemplo, tengo dos tablas List y ListItems. Necesito una forma rápida de eliminar todos los elementos de lista de una lista determinada.
Ahora la parte interesante de eliminar los elementos y actualizar el marco de Entity usando una extensión.
El código principal ahora puede usarlo es como
fuente
Si desea eliminar todas las filas de una tabla, puede ejecutar el comando sql
TRUNCATE TABLE (Transact-SQL) Elimina todas las filas de una tabla sin registrar las eliminaciones de filas individuales. TRUNCATE TABLE es similar a la instrucción DELETE sin cláusula WHERE; sin embargo, TRUNCATE TABLE es más rápido y utiliza menos recursos del sistema y del registro de transacciones.
fuente
truncate table
en tablas a las que hace referencia una restricción FOREIGN KEY. (Puede truncar una tabla que tiene una clave externa que hace referencia a sí misma). Documentación de MSDNUUHHIVS
's es una forma muy elegante y rápida de eliminar lotes, pero debe usarse con cuidado:context.SaveChanges()
Estos problemas pueden evitarse tomando el control de la transacción. El siguiente código ilustra cómo eliminar por lotes e insertar en masa de manera transaccional:
fuente
Entity Framework Core
Resumen :
Observaciones :
fuente
Puede ejecutar consultas sql directamente de la siguiente manera:
Para seleccionar podemos usar
fuente
También puede usar el método DeleteAllOnSubmit () pasando sus resultados en una lista genérica en lugar de en var. De esta manera, su foreach se reduce a una línea de código:
Sin embargo, probablemente todavía use un bucle interno.
fuente
var
es.La respuesta de Thanh funcionó mejor para mí. Eliminé todos mis registros en un solo viaje de servidor. Me costó realmente llamar al método de extensión, así que pensé en compartir el mío (EF 6):
Agregué el método de extensión a una clase auxiliar en mi proyecto MVC y cambié el nombre a "RemoveWhere". Inyecto un dbContext en mis controladores, pero también podría hacer un
using
.Esto generó una sola declaración de eliminación para el grupo.
fuente
EF 6. =>
fuente
Mejor:
in EF6 => .RemoveRange()
Ejemplo:
fuente
Vea la respuesta 'bit de código favorito' que funciona
Así es como lo usé:
fuente
En EF 6.2 esto funciona perfectamente, enviando la eliminación directamente a la base de datos sin cargar primero las entidades:
Con un predicado fijo es bastante sencillo:
Y si necesita un predicado dinámico, eche un vistazo a LINQKit (paquete Nuget disponible), algo como esto funciona bien en mi caso:
fuente
Z.EntityFramework.Plus
o algo similar? ( entityframework.net/batch-delete )Delete()
método es inherentemente inexistente).