Jon*_*way 292 entity-framework
我正在使用Entity Framework从表中删除多个项目.没有外键/父对象,因此我无法使用OnDeleteCascade处理此问题.
现在我这样做:
var widgets = context.Widgets
.Where(w => w.WidgetId == widgetId);
foreach (Widget widget in widgets)
{
context.Widgets.DeleteObject(widget);
}
context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
它有效但是foreach让我烦恼.我正在使用EF4,但我不想执行SQL.我只是想确保我没有遗漏任何东西 - 这一切都很好,对吧?我可以用扩展方法或帮助器来抽象它,但在某个地方我们仍然会做一个foreach,对吧?
Kyl*_*yle 628
EntityFramework 6使这更容易了.RemoveRange().
例:
db.People.RemoveRange(db.People.Where(x => x.State == "CA"));
db.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
Kla*_*sen 73
这是好事,对吧?我可以用扩展方法或帮助器来抽象它,但在某个地方我们仍然会做一个foreach,对吧?
嗯,是的,除了你可以把它变成两个班轮:
context.Widgets.Where(w => w.WidgetId == widgetId)
.ToList().ForEach(context.Widgets.DeleteObject);
context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
Vla*_*den 69
using (var context = new DatabaseEntities())
{
context.ExecuteStoreCommand("DELETE FROM YOURTABLE WHERE CustomerID = {0}", customerId);
}
Run Code Online (Sandbox Code Playgroud)
小智 45
我知道它已经很晚了但是如果有人需要一个简单的解决方案,那么很酷的是你也可以用它添加where子句:
public static void DeleteWhere<T>(this DbContext db, Expression<Func<T, bool>> filter) where T : class
{
string selectSql = db.Set<T>().Where(filter).ToString();
string fromWhere = selectSql.Substring(selectSql.IndexOf("FROM"));
string deleteSql = "DELETE [Extent1] " + fromWhere;
db.Database.ExecuteSqlCommand(deleteSql);
}
Run Code Online (Sandbox Code Playgroud)
注意:刚用MSSQL2008测试过.
更新:
当EF生成带参数的 sql语句时,上面的解决方案将不起作用,所以这里是EF5的更新:
public static void DeleteWhere<T>(this DbContext db, Expression<Func<T, bool>> filter) where T : class
{
var query = db.Set<T>().Where(filter);
string selectSql = query.ToString();
string deleteSql = "DELETE [Extent1] " + selectSql.Substring(selectSql.IndexOf("FROM"));
var internalQuery = query.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(field => field.Name == "_internalQuery").Select(field => field.GetValue(query)).First();
var objectQuery = internalQuery.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(field => field.Name == "_objectQuery").Select(field => field.GetValue(internalQuery)).First() as ObjectQuery;
var parameters = objectQuery.Parameters.Select(p => new SqlParameter(p.Name, p.Value)).ToArray();
db.Database.ExecuteSqlCommand(deleteSql, parameters);
}
Run Code Online (Sandbox Code Playgroud)
它需要一点点反射,但效果很好.
ihe*_*heb 35
最后,在Entity Framework Core 7中通过以下命令引入了批量删除ExecuteDelete:
context.Widgets
.Where(w => w.WidgetId == widgetId)
.ExecuteDelete();
Run Code Online (Sandbox Code Playgroud)
这里需要注意的是,根据其文档,ExecuteDelete不需要 a :SaveChanges
此操作立即针对数据库执行,而不是推迟到调用 DbContext.SaveChanges() 为止。它还不会以任何方式与 EF 更改跟踪器交互:调用此操作时恰好被跟踪的实体实例不会被考虑在内,也不会更新以反映更改。
我知道这个问题是针对 EF4 提出的,但如果您升级的话,这是一个不错的选择!
Mar*_*son 30
对于使用EF5的任何人,可以使用以下扩展库:https://github.com/loresoft/EntityFramework.Extended
context.Widgets.Delete(w => w.WidgetId == widgetId);
Run Code Online (Sandbox Code Playgroud)
Luk*_* Vo 22
这个答案适用于 EF Core 7(我不知道他们现在是否将 EF Core 与 EF 合并,在他们将两者分开之前)。
EF Core 7 现在支持ExecuteUpdate 和 ExecuteDelete(批量更新):
// Delete all Tags (BE CAREFUL!)
await context.Tags.ExecuteDeleteAsync();
// Delete Tags with a condition
await context.Tags.Where(t => t.Text.Contains(".NET")).ExecuteDeleteAsync();
Run Code Online (Sandbox Code Playgroud)
等效的 SQL 查询是:
DELETE FROM [t]
FROM [Tags] AS [t]
DELETE FROM [t]
FROM [Tags] AS [t]
WHERE [t].[Text] LIKE N'%.NET%'
Run Code Online (Sandbox Code Playgroud)
Ngu*_*anh 16
实体框架核心
3.1 3.0 2.2 2.1 2.0 1.1 1.0
using (YourContext context = new YourContext ())
{
var widgets = context.Widgets.Where(w => w.WidgetId == widgetId);
context.Widgets.RemoveRange(widgets);
context.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
总结:
从集合底层的上下文中删除给定的实体集合,每个实体都被置于已删除状态,以便在调用 SaveChanges 时将其从数据库中删除。
备注:
请注意,如果 System.Data.Entity.Infrastructure.DbContextConfiguration.AutoDetectChangesEnabled 设置为 true(这是默认值),则 DetectChanges 将在删除任何实体之前调用一次,并且不会再次调用。这意味着在某些情况下,RemoveRange 的性能可能比多次调用 Remove 的性能要好得多。请注意,如果上下文中存在任何处于已添加状态的实体,则此方法将使其与上下文分离。这是因为假定已添加实体不存在于数据库中,因此尝试删除它是没有意义的。
Edw*_*rey 11
仍然似乎很疯狂,不得不从服务器拉回任何东西只是为了删除它,但至少回到ID只是比拉下整个实体更精简:
var ids = from w in context.Widgets where w.WidgetId == widgetId select w.Id;
context.Widgets.RemoveRange(from id in ids.AsEnumerable() select new Widget { Id = id });
Run Code Online (Sandbox Code Playgroud)
jzm*_*jzm 10
EF 6.1
public void DeleteWhere<TEntity>(Expression<Func<TEntity, bool>> predicate = null)
where TEntity : class
{
var dbSet = context.Set<TEntity>();
if (predicate != null)
dbSet.RemoveRange(dbSet.Where(predicate));
else
dbSet.RemoveRange(dbSet);
context.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
用法:
// Delete where condition is met.
DeleteWhere<MyEntity>(d => d.Name == "Something");
Or:
// delete all from entity
DeleteWhere<MyEntity>();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
287478 次 |
| 最近记录: |