启用 RemoveRange 以通过实体上的谓词删除

Enable RemoveRange to remove by predicate on entity

在业务层中,在删除与本身正在删除的实体的关系时有很多重复代码(没有数据库级联删除的好处)。除了相关的实体删除用例之外,还可以使用一种好的方法来减少通过任何匹配谓词删除记录所需的代码,例如通过 id 等。

// Simple example removing phone numbers from people entity
// The "personId" is an identifier passed into the method performing the deletion
var phones = _context.Phones
    .Where(m => m.PersonId == personId)
    .ToList();
if (phones.Count > 0)
    _context.Phones.RemoveRange(phones);

我将此作为我提出的解决方案的问答发布,以便稍后查找。绝对希望看到其他方法。

一种方法是使用表达式重载 DbSet 上的 RemoveRange 方法。为了尽可能方便,将其实现为 DbSet 实体本身的方法扩展,以便使用实际的 RemoveRange 方法将过程简单地重载到 DbSet 上。

public static class DataExtensions
{
    public static void RemoveRange<TEntity>(
        this System.Data.Entity.DbSet<TEntity> entities,
        System.Linq.Expressions.Expression<Func<TEntity, bool>> predicate)
        where TEntity : class
    {
        var records = entities
            .Where(predicate)
            .ToList();
        if (records.Count > 0)
            entities.RemoveRange(records);
    }
}

有了这个扩展,现在可以像 Where 一样调用 RemoveRange。

_context.Phones.RemoveRange(m => m.PersonId == personId);

另一种选择是直接使用SQL:

context.Database.ExecuteSqlCommand("DELETE FROM Phones WHERE PersonId=@pid", personId) 

https://msdn.microsoft.com/en-us/library/gg679456%28v=vs.113%29.aspx

EF 有一个扩展,可以在单个 DML 语句上对多个记录运行 UPDATE 和 DELETE 查询

我不记得语法了,但与

相似
context.Phones.Delete(p => p.PersonId == personId)  

这条 LINQ 语句变成

DELETE FROM Phones WHERE PersonId = ?

https://github.com/loresoft/EntityFramework.Extended