Подтвердить что ты не робот

Как удалить все элементы в DbSet?

Какой лучший способ удалить все элементы в System.Data.Entity.DbSet с помощью Entity Framework 4.3?

4b9b3361

Ответ 1

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 и удалить объекты по одному из набора. Более того, когда вы вызываете SaveChanges, EF отправит n (= количество сущностей в наборе) операторов DELETE в базу данных, которые также выполняются один за другим в БД (в одной транзакции).

Итак, прямой SQL явно предпочтительнее для этой цели, поскольку вам нужен только один оператор DELETE.

Ответ 2

Вот еще один способ сделать это в коде.

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>();

Ответ 3

Если вы хотите удалить все элементы без записи SQL и выполнить только Single Db Call

Расширенная библиотека Entity Framework предлагает метод пакетного удаления.

context.Users.Delete();

Ответ 4

Поскольку в принятом ответе упоминается только о методе ниже:

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()

Ответ 5

Если вы работаете с единицей работы и общим репозиторием, вы можете найти следующие полезные

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();

Ответ 6

Вы можете добиться этого, используя прямой запрос:

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