我正在使用实体框架从表中删除几个项目。没有外键/父对象,所以我不能用OnDeleteCascade处理这个。

现在我正在做这个:

var widgets = context.Widgets
    .Where(w => w.WidgetId == widgetId);

foreach (Widget widget in widgets)
{
    context.Widgets.DeleteObject(widget);
}
context.SaveChanges();

它工作,但foreach困扰我。我使用EF4,但我不想执行SQL。我只是想确保我没有错过任何东西-这是最好的,对吧?我可以用扩展方法或helper来抽象它,但在某些地方我们还是要用foreach,对吧?


当前回答

从服务器上拉回任何东西来删除它看起来仍然很疯狂,但至少只返回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 });

其他回答

你可以使用像EntityFramework这样的扩展库。Extended或Z.EntityFramework.Plus。EF6,有EF 5, 6或核心可用。当你必须删除或更新时,这些库具有出色的性能,并且它们使用LINQ。删除(source +)的示例:

ctx.Users。Where(x => x. lastlogindate < DateTime.Now.AddYears(-2)) delete ();

或(来源扩展)

context.Users。Where(u => u.FirstName == "firstname") delete ();

它们使用本地SQL语句,因此性能非常好。

你也可以使用DeleteAllOnSubmit()方法,通过将你的结果传递在一个通用列表中,而不是在var中。这样你的foreach减少到一行代码:

List<Widgets> widgetList = context.Widgets
              .Where(w => w.WidgetId == widgetId).ToList<Widgets>();

context.Widgets.DeleteAllOnSubmit(widgetList);

context.SubmitChanges();

它可能仍然在内部使用循环。

这已经够好了,对吧?我可以用扩展来抽象它 方法或助手,但我们还是会用到 foreach ?

是的,不过你可以把它写成两行字:

context.Widgets.Where(w => w.WidgetId == widgetId)
               .ToList().ForEach(context.Widgets.DeleteObject);
context.SaveChanges();

EF 6.=>

var assignmentAddedContent = dbHazirBot.tbl_AssignmentAddedContent.Where(a =>
a.HazirBot_CategoryAssignmentID == categoryAssignment.HazirBot_CategoryAssignmentID);
dbHazirBot.tbl_AssignmentAddedContent.RemoveRange(assignmentAddedContent);
dbHazirBot.SaveChanges();

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

用法:

// Delete where condition is met.
DeleteWhere<MyEntity>(d => d.Name == "Something");

Or:

// delete all from entity
DeleteWhere<MyEntity>();