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



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

603   7  

7 ответов:

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

но в обоих случаях вы должны загрузить все объекты или все ключевые свойства и удалить объекты по одному из набора. Более того, когда вы звоните SaveChanges эф будет отправить N (=количество сущностей в наборе) инструкции DELETE в базу данных, которые также выполняются один за другим в БД (в одной транзакции).

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

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

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

старый пост, но теперь есть метод RemoveRange:

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

Если вы хотите удалить все элементы без написания SQL и выполнить только Один Вызов БД

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

context.Users.Delete();

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

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

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

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

вы можете достичь этого с помощью прямого запроса:

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

Comments

    Ничего не найдено.