C# 如何将RemoveRange与1-query-approach实体框架一起使用6

C# 如何将RemoveRange与1-query-approach实体框架一起使用6,c#,entity-framework,crud,C#,Entity Framework,Crud,我正在寻找一种使用1-query-approach执行RemoveRange()的方法。使用Remove()方法,其工作原理如下: public void Delete() { Record record = new Record() { id = 1, value = 5 }; using(SomeContext ctx = new SomeContext()) { ctx.Records.Entry(record).St

我正在寻找一种使用1-query-approach执行
RemoveRange()
的方法。使用
Remove()
方法,其工作原理如下:

public void Delete()
{
    Record record = new Record() {
        id = 1,
        value = 5
    };
    using(SomeContext ctx = new SomeContext()) {
        ctx.Records.Entry(record).State = EntityState.Deleted;
        ctx.SaveChanges();
    }
}
但同样的方法不适用于
RemoveRange()
。EF文档说明该方法将每个实体设置为
EntityState.Deleted
。如果按照我的理解是这样的话,这将起作用:

public void DeleteAll()
{
    List<Record> records = new List<Record>() {
        new Record() { id = 1, value = 5 },
        new Record() { id = 2, value = 10 }
    };
    using(SomeContext ctx = new SomeContext()) {
        ctx.Records.RemoveRange(records);
        ctx.SaveChanges();
    }
}

我可以使用此方法而不通过单独的查询从数据库中检索所有项目吗?

当您使用
ctx.Entry(item)
时,它会将此项目添加到上下文跟踪中,然后您可以对其进行编辑。使用
RemoveRange
时,它不会首先隐式地添加到数据上下文中,这就是为什么会出现异常。 在
RemoveRange

编辑:

另一种方法。这是
RemoveRange
在幕后的一点做法。它首先禁用
AutoDetectChanges
,删除它应该删除的内容,然后调用
DetectChanges
。可以用扩展方法将其包装,使其再次成为一行程序

public void DeleteAll()
{
    List<Record> records = new List<Record>() {
        new Record() { id = 1, value = 5 },
        new Record() { id = 2, value = 10 }
    };
    using(SomeContext ctx = new SomeContext()) {
        ctx.Configuration.AutoDetectChangesEnabled = false;
        foreach(var item in records)
        {
            ctx.Entry(item).State = EntityState.Deleted;
        }
        ctx.ChangeTracker.DetectChanges();
        ctx.SaveChanges();
    }
}
public void DeleteAll()
{
列表记录=新列表(){
新记录(){id=1,value=5},
新记录(){id=2,value=10}
};
使用(SomeContext ctx=new SomeContext()){
ctx.Configuration.AutoDetectChangesEnabled=false;
foreach(记录中的var项目)
{
ctx.Entry(item).State=EntityState.Deleted;
}
ctx.ChangeTracker.DetectChanges();
ctx.SaveChanges();
}
}

我发现您的实体集合已分离(在那里创建时),因此objectContext无法跟踪它。您可能需要附加它。您可以按以下方式执行此操作:

//Find all records in database with an id that is in your record collection 
var recordsToBeDeleted = ctx.Records.Where(dbr => records.Any(r => r.id == dbr.id));
ctx.Records.RemoveRange(recordsToBeDeleted);
context.SaveChanges();

获取的解决方案在EF文档中找不到该方法。你是说定制方法吗?它足够快吗?可能是EF核心唯一的方法,没有意识到它可能不在EF6中。对不起,编辑是我想要的,这是一种饮食习惯吗?它会比使用
ctx.Records.Where(dbr=>Records.Any(r=>r.id==dbr.id))从数据库检索集合更快吗?或者改变状态也一样?它是否执行查询以从数据库中获取每条记录?我不太确定,我认为它可能执行查询以获取
条目。但只有在添加查询记录器并自己检查时才能确定。如果你到星期一还没到,我会查一查。在家中没有设置EF:)@VitaliiIsaenko使用EF6对其进行了测试,
条目
不会创建对数据库的查询。它只在您调用
SaveChanges
时查询数据库。关于你的问题,如果这是一个好的做法,我会说不。虽然这减少了查询量,但也容易产生错误。如果将数据库中不存在的条目设置为“已删除”,则会引发并发异常。我总是从数据库中获取条目,然后删除。谢谢,但这需要在删除之前执行对数据库的查询。我确切地知道这些对象存在于数据库中,所以我想删除记录而不首先检索它们。
public void DeleteAll()
{
    List<Record> records = new List<Record>() {
        new Record() { id = 1, value = 5 },
        new Record() { id = 2, value = 10 }
    };
    using(SomeContext ctx = new SomeContext()) {
        ctx.Configuration.AutoDetectChangesEnabled = false;
        foreach(var item in records)
        {
            ctx.Entry(item).State = EntityState.Deleted;
        }
        ctx.ChangeTracker.DetectChanges();
        ctx.SaveChanges();
    }
}
//Find all records in database with an id that is in your record collection 
var recordsToBeDeleted = ctx.Records.Where(dbr => records.Any(r => r.id == dbr.id));
ctx.Records.RemoveRange(recordsToBeDeleted);
context.SaveChanges();