web-dev-qa-db-ja.com

DbSet内のすべての要素を削除するにはどうすればよいですか?

Entity Framework 4.3でSystem.Data.Entity.DbSetのすべての要素を削除する最良の方法は何ですか?

68
aknuds1
dbContext.Database.ExecuteSqlCommand("delete from MyTable");

(冗談ではありません。)

問題は、EFはバッチコマンドをサポートしていないことであり、直接DMLを使用せずにセット内のすべてのエンティティを削除する唯一の方法は次のとおりです。

foreach (var entity in dbContext.MyEntities)
    dbContext.MyEntities.Remove(entity);
dbContext.SaveChanges();

または、完全なエンティティのロードを回避するために、少し安いかもしれません:

foreach (var id in dbContext.MyEntities.Select(e => e.Id))
{
    var entity = new MyEntity { Id = id };
    dbContext.MyEntities.Attach(entity);
    dbContext.MyEntities.Remove(entity);
}
dbContext.SaveChanges();

ただし、どちらの場合も、allエンティティまたはallキープロパティをロードし、セットからエンティティを1つずつ削除する必要があります。さらに、SaveChangesを呼び出すと、EFはn(=セット内のエンティティの数)のDELETEステートメントをデータベースに送信します。これらのステートメントは、DBで1つずつ(単一のトランザクションで)実行されます。

したがって、単一のDELETEステートメントのみが必要なので、この目的には直接SQLが明らかに望ましいです。

97
Slauma

古い投稿ですが、RemoveRangeメソッドがあります:

    dbContext.MyEntities.RemoveRange(dbContext.MyEntities);
    dbContext.SaveChanges();
15
jintux

コードでそれを行う別の方法を次に示します。

public static class Extensions
{
    public static void DeleteAll<T>(this DbContext context)
        where T : class
    {
        foreach (var p in context.Set<T>())
        {
            context.Entry(p).State = EntityState.Deleted;
        }
    }
}

実際にメソッドを呼び出してセットをクリアするには:

myDbContext.DeleteAll<MyPocoClassName>();
15
Tim Cooke

すべての要素を削除する場合SQLを記述せずにを実行し、Single Db Callのみを実行します

Entity Framework Extended Librarybatch deleteメソッドを提供します。

context.Users.Delete();
3

受け入れられた回答では、以下の方法についてのみ言及しています。

context.Database.ExecuteSqlCommand("delete from MyTable");

代わりに代替手段を提供します。すべてのエンティティの読み込みを回避するために使用できるメソッドを記述し、それらをループしてExecuteSqlCommand代わりに。

コンテキストがDbContextである作業単位を使用すると仮定します。

using System.Data.Entity.Core.Objects;
using System.Text.RegularExpressions;

public void DeleteAll()
{
    ObjectContext objectContext = ( (IObjectContextAdapter)context ).ObjectContext;
    string sql = objectContext.CreateObjectSet<T>().ToTraceString();
    Regex regex = new Regex( "FROM (?<table>.*) AS" );
    Match match = regex.Match( sql );
    string tableName = match.Groups[ "table" ].Value;

    context.Database.ExecuteSqlCommand( string.Format( "delete from {0}", tableName ) );
}

コードの最初のブロックは、ExecuteSqlCommandメソッドで必要なテーブル名を取得します。

使用法:

using ( var context = new UnitOfWork() )
{
    context.MyRepository.DeleteAll();
}

不要があります

context.SaveChanges()
2
Ryfcia

作業ユニットと汎用リポジトリを使用している場合、次のことが役立つ場合があります。

public virtual void DeleteWhere(Expression<Func<TEntity, bool>> filter = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
            string includeProperties = "")
        {
            IQueryable<TEntity> query = dbSet;
            if (filter != null)
            {
                query = query.Where(filter);
            }
            foreach (var includeProperty in includeProperties.Split
                (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
            {
                query = query.Include(includeProperty);
            }

            foreach (var entity in query)
            {
                context.Entry(entity).State = EntityState.Deleted;
            }
        }

使用法:

uow.myRepositoryName.DeleteWhere(u => u.RoomId == roomId);
uow.Save();
1
user2330270

直接クエリを使用してこれを実現できます。

 ent.Database.ExecuteSqlCommand("delete from tablename");
0