it-swarm.com.de

Entity Framework. Löschen Sie alle Zeilen in der Tabelle

Wie kann ich mit Entity Framework schnell alle Zeilen in der Tabelle entfernen?

Ich benutze derzeit:

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

Die Ausführung dauert jedoch lange.

Gibt es Alternativen?

249
Zhenia

Für diejenigen, die das googeln und wie ich hier gelandet sind, ist dies derzeit in EF5 und EF6 der Fall:

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

Angenommen, der Kontext ist ein System.Data.Entity.DbContext

272
Ron Sijm

Warnung: Das Folgende ist nur für kleine Tabellen geeignet (denken Sie <1000 Zeilen)

In der folgenden Lösung werden die Zeilen mithilfe des Entity-Frameworks (nicht SQL) gelöscht, sodass es nicht für die SQL Engine (R/DBM) spezifisch ist.

Dies setzt voraus, dass Sie dies zum Testen oder in einer ähnlichen Situation tun. Entweder

  • Die Datenmenge ist klein oder
  • Die Leistung spielt keine Rolle

Rufen Sie einfach an:

VotingContext.Votes.RemoveRange(VotingContext.Votes);

Angenommen, dieser Kontext:

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;}
}

Für saubereren Code können Sie die folgende Erweiterungsmethode deklarieren:

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

Dann wird das Obige:

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

Vor kurzem habe ich diesen Ansatz verwendet, um meine Testdatenbank für jeden Testfalllauf zu bereinigen (dies ist offensichtlich schneller als jedes Mal eine Neuerstellung der Datenbank von Grund auf, obwohl ich die Form der generierten Löschbefehle nicht überprüft habe).


Warum kann es langsam sein?

  1. EF erhält ALLE Zeilen (VotingContext.Votes)
  2. und dann werden ihre IDs (nicht genau, wie, egal) verwendet, um sie zu löschen.

Wenn Sie also mit einer großen Datenmenge arbeiten, beenden Sie den SQL Server-Prozess (er belegt den gesamten Speicher) und das Gleiche für den IIS) -Prozess, da EF alle Daten zwischenspeichert Genauso wie SQL Server. Verwenden Sie diesen nicht, wenn Ihre Tabelle eine ernsthafte Datenmenge enthält.

191
Ahmed Alejo

Verwenden von SQLs TRUNCATE TABLE Befehl ist der schnellste, da er für die Tabelle und nicht für einzelne Zeilen ausgeführt wird.

dataDb.ExecuteStoreCommand("TRUNCATE TABLE [Table]");

Angenommen, dataDb ist ein DbContext (kein ObjectContext), können Sie es umbrechen und die folgende Methode verwenden:

var objCtx = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)dataDb).ObjectContext;
objCtx.ExecuteStoreCommand("TRUNCATE TABLE [Table]");
84
Rudi Visser
var all = from c in dataDb.Table select c;
dataDb.Table.RemoveRange(all);
dataDb.SaveChanges();
37
user3328890
using (var context = new DataDb())
{
     var ctx = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)context).ObjectContext;
     ctx.ExecuteStoreCommand("DELETE FROM [TableName] WHERE Name= {0}", Name);
}

oder

using (var context = new DataDb())
{
     context.Database.ExecuteSqlCommand("TRUNCATE TABLE [TableName]");
}
33
Manish Mishra

Dies vermeidet die Verwendung von SQL

using (var context = new MyDbContext())
{
    var itemsToDelete = context.Set<MyTable>();
    context.MyTables.RemoveRange(itemsToDelete);
    context.SaveChanges();
}
14
Rob Sedgwick

Sie können das ohne Foreach tun

dataDB.Table.RemoveRange(dataDB.Table);
dataDB.SaveChanges();

Dadurch werden alle Zeilen entfernt

12
Omid Farvid

Ich bin auf diese Frage gestoßen, als ich mich mit einem bestimmten Fall befassen musste: vollständige Aktualisierung des Inhalts in einer "Blatt" -Tabelle (keine FKs, die darauf verweisen). Dies beinhaltete das Entfernen aller Zeilen und das Einfügen neuer Zeileninformationen und sollte transaktional erfolgen (ich möchte nicht mit einer leeren Tabelle enden, wenn Einfügungen aus irgendeinem Grund fehlschlagen).

Ich habe den Ansatz public static void Clear<T>(this DbSet<T> dbSet) ausprobiert, aber es werden keine neuen Zeilen eingefügt. Ein weiterer Nachteil ist, dass der gesamte Prozess langsam ist, da die Zeilen einzeln gelöscht werden.

Also habe ich auf TRUNCATE umgestellt, da es viel schneller ist und es auch ROLLBACKable ist. Es setzt auch die Identität zurück.

Beispiel mit Repository-Muster:

public class Repository<T> : IRepository<T> where T : class, new()
{
    private readonly IEfDbContext _context;

    public void BulkInsert(IEnumerable<T> entities)
    {
        _context.BulkInsert(entities);
    }

    public void Truncate()
    {
        _context.Database.ExecuteSqlCommand($"TRUNCATE TABLE {typeof(T).Name}");
    }
 }

 // usage 
 DataAccess.TheRepository.Truncate();
 var toAddBulk = new List<EnvironmentXImportingSystem>();

 // fill toAddBulk from source system
 // ...

 DataAccess.TheRepository.BulkInsert(toAddBulk);
 DataAccess.SaveChanges();

Wie bereits erwähnt, kann diese Lösung natürlich nicht von Tabellen verwendet werden, auf die durch Fremdschlüssel verwiesen wird (TRUNCATE schlägt fehl).

9
Alexei

wenn

      using(var db = new MyDbContext())
            {
               await db.Database.ExecuteSqlCommandAsync(@"TRUNCATE TABLE MyTable"););
            }

ursachen

Die Tabelle 'MyTable' kann nicht abgeschnitten werden, da auf sie von einer FOREIGN KEY-Einschränkung verwiesen wird.

Ich benutze das :

      using(var db = new MyDbContext())
               {
                   await db.Database.ExecuteSqlCommandAsync(@"DELETE FROM MyTable WHERE ID != -1");
               }
4
Zakos

Wenn Sie Ihre gesamte Datenbank löschen möchten.

Aufgrund der Fremdschlüsseleinschränkungen ist es wichtig, in welcher Reihenfolge die Tabellen abgeschnitten werden. Dies ist eine Möglichkeit, diese Sequenz zu brachialisieren.

    public static void ClearDatabase<T>() where T : DbContext, new()
    {
        using (var context = new T())
        {
            var tableNames = context.Database.SqlQuery<string>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME NOT LIKE '%Migration%'").ToList();
            foreach (var tableName in tableNames)
            {
                foreach (var t in tableNames)
                {
                    try
                    {

                        if (context.Database.ExecuteSqlCommand(string.Format("TRUNCATE TABLE [{0}]", tableName)) == 1)
                            break;

                    }
                    catch (Exception ex)
                    {

                    }
                }
            }

            context.SaveChanges();
        }
    }

verwendungszweck:

ClearDatabase<ApplicationDbContext>();

denken Sie daran, Ihren DbContext danach erneut zu initialisieren.

4
Kristian Nissen
var data = (from n in db.users select n);
db.users.RemoveRange(data);
db.SaveChanges();
4
DBB

Dies funktioniert ordnungsgemäß in EF 5:

YourEntityModel myEntities = new YourEntityModel();

var objCtx = ((IObjectContextAdapter)myEntities).ObjectContext;
objCtx.ExecuteStoreCommand("TRUNCATE TABLE [TableName]");
1
Hekmat

Löschen Sie alle Datensätze. Setzen Sie den Primärindex nicht wie "Abschneiden" zurück.

/// <summary>
/// SET - DELETE all record by table - no truncate - return deleted records
/// </summary>
public static int setListDelAllMYTABLE()
{
    // INIT
    int retObj = 0;
    using (MYDBEntities ctx = new MYDBEntities())
    {
        // GET - all record
        var tempAllRecord = ctx.MYTABLE.ToList();
        // RESET
        ctx.MYTABLE.RemoveRange(tempAllRecord);
        // SET - final save
        retObj += ctx.SaveChanges();
    }
    // RET
    return retObj;
}
0
Roberto Mutti