使用Entity Framework和Microsoft Azure批量删除

时间:2014-04-14 08:43:28

标签: entity-framework azure-sql-database

我使用Entity Framework 6.1,MVC5,ASP.NET 4.5和Azure网站(免费)+ Azure SQL。

当我尝试删除45 000个实体时,需要45分钟以上。我的实体中有导航属性。

我试过了:

context.Contacts.RemoveRange(db.Groups.Find(id).Contacts.ToList());

而且:

foreach(var contact in db.Groups.Find(id).Contacts.ToList())
{
    context.Database.ExecuteSqlCommand("DELETE FROM Contacts WHERE ContactID = {0}", contact.ContactID);
}

我确定这不正常......但是造成这个问题的原因是什么?

1 个答案:

答案 0 :(得分:0)

当您呼叫.ToList()时,您将所有这些实体撤回到内存中以便开始。然后通过循环遍历这些,如果我了解你的情况,你就可以有效地调用相同的SQL 45000次。

您不需要返回整个对象来删除它。我建议只需在查询中选择ID即可删除要删除的联系人的ID:

var ids = db.Groups.Find(id).Contacts.Select(x => x.ContactId).ToList();

然后我会考虑实现EntityFrameworkExtensions库(https://github.com/loresoft/EntityFramework.Extended)来帮助处理这个问题(确保批量删除),或者使用IN查询,例如DELETE FROM Contacts WHERE ContactID IN (1,2,3,....)但是再次确保批处理。

Extensions库允许您执行删除操作:

m_context.Contacts.Delete(x => idList.Contains(x.ContactId));

但请注意,这将立即执行,而不是在您致电SaveChanges()

时执行

总体而言,代码将是这样的:

public int RemoveContacts(IList<int> _ids)
{
    int index = 0;
    int numDeleted = 0;
    while (index < _ids.Count())
    {
        var batch= _ids.Skip(index).Take(MAX_BATCH_SIZE);

        //Using extensions method
        numDeleted += context.Contacts.Delete(x => batch.Contains(x.ContactId));

        //Using SQL
        context.Database.ExecuteSqlCommand("DELETE FROM Contacts WHERE ContactID IN {0}", batch);
        index += MAX_BATCH_SIZE;
    }
    return numDeleted ;
}