Marco de la entidad. Eliminar todas las filas de la tabla

Resuelto Zhenia asked hace 11 años • 0 respuestas

¿Cómo puedo eliminar rápidamente todas las filas de la tabla usando Entity Framework?

Actualmente estoy usando:

var rows = from o in dataDb.Table
           select o;
foreach (var row in rows)
{
    dataDb.Table.Remove(row);
}
dataDb.SaveChanges();

Sin embargo, lleva mucho tiempo ejecutarlo.

¿Hay alguna alternativa?

Zhenia avatar Mar 05 '13 16:03 Zhenia
Aceptado

Para aquellos que están buscando esto en Google y terminaron aquí como yo, así es como lo hacen actualmente en EF5 y EF6:

context.Database.ExecuteSqlCommand("TRUNCATE TABLE [TableName]");

Asumir que el contexto es unSystem.Data.Entity.DbContext

Editar:

Actualmente en net6.0 (dotnet 6 core) puedes hacer lo siguiente:

context.Database.ExecuteSqlRaw("TRUNCATE TABLE [TableName]");

O use la sobrecarga asíncrona:

await context.Database.ExecuteSqlRawAsync("TRUNCATE TABLE [TableName]");

Estos son métodos de extensión provenientes deMicrosoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions

Si tiene problemas con las claves externas (en MySql), es posible que deba hacer lo siguiente (hacer la SET FOREIGN_KEY_CHECKS = 0;parte en una llamada separada no parece funcionar para mí)

context.Database.ExecuteSqlRaw("SET FOREIGN_KEY_CHECKS = 0; TRUNCATE TABLE [TableName];");

Entonces, si desea truncar toda su base de datos (posiblemente por razones de prueba unitaria), puede hacer lo siguiente:

var tableNames = context.Model.GetEntityTypes()
    .Select(t => t.GetTableName())
    .Distinct()
    .ToList();

foreach (var tableName in tableNames)
{
    context.Database.ExecuteSqlRaw($"SET FOREIGN_KEY_CHECKS = 0; TRUNCATE TABLE `{tableName}`;");
}
Ron Sijm avatar Sep 24 '2013 16:09 Ron Sijm

Advertencia: lo siguiente solo es adecuado para tablas pequeñas (piense en <1000 filas)

Aquí hay una solución que utiliza el marco de entidad (no SQL) para eliminar las filas, por lo que no es específica de SQL Engine (R/DBM).

Esto supone que estás haciendo esto para realizar pruebas o alguna situación similar. Cualquiera

  • La cantidad de datos es pequeña o
  • El rendimiento no importa

Simplemente llama:

VotingContext.Votes.RemoveRange(VotingContext.Votes);

Asumiendo este contexto:

public class VotingContext : DbContext
{
    public DbSet<Vote> Votes{get;set;}
    public DbSet<Poll> Polls{get;set;}
    public DbSet<Voter> Voters{get;set;}
    public DbSet<Candidacy> Candidates{get;set;}
}

Para un código más ordenado, puede declarar el siguiente método de extensión:

public static class EntityExtensions
{
    public static void Clear<T>(this DbSet<T> dbSet) where T : class
    {
        dbSet.RemoveRange(dbSet);
    }
}

Entonces lo anterior se convierte en:

VotingContext.Votes.Clear();
VotingContext.Voters.Clear();
VotingContext.Candidacy.Clear();
VotingContext.Polls.Clear();
await VotingTestContext.SaveChangesAsync();

Recientemente utilicé este enfoque para limpiar mi base de datos de prueba para cada ejecución de caso de prueba (obviamente es más rápido que recrear la base de datos desde cero cada vez, aunque no verifiqué la forma de los comandos de eliminación que se generaron).


¿Por qué puede ser lento?

  1. EF obtendrá TODAS las filas (VotingContext.Votes)
  2. y luego usará sus ID (no estoy seguro exactamente cómo, no importa) para eliminarlos.

Entonces, si está trabajando con una gran cantidad de datos, cancelará el proceso del servidor SQL (consumirá toda la memoria) y lo mismo ocurre con el proceso IIS, ya que EF almacenará en caché todos los datos de la misma manera que el servidor SQL. No utilice este si su tabla contiene una gran cantidad de datos.

Ahmed Alejo avatar Jul 01 '2014 22:07 Ahmed Alejo