Какой лучший способ удалить все элементы в System.Data.Entity.DbSet с помощью Entity Framework 4.3?
Как удалить все элементы в DbSet?
Ответ 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");