实体框架:仅当所有对象都存在时更新多个对象

2024-06-16 09:56:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用C#编写一个PATCHRESTAPI,使用实体框架更新多个对象中的特定字段。
请求机构:

{
  "ids": [
    "id1",
    "id2"
  ],
  "foo": "bar"
}

我想将所有对象的foo字段更新为bar,但前提是所有对象都存在。

我试图保持它干净,没有一个先发制人的选择来检查是否所有对象都存在(顺便说一句,这可能不够好,因为如果一个对象现在存在,并不意味着它在几毫秒后仍然存在)

我正在寻找一个简短的解决方案,如果其中一个对象没有成功更新(或不存在),它将回滚并引发异常。
我找到的唯一解决方案是打开一个事务并更新循环中的每个对象,这不是最好的方法,因为我不想一次访问每一行的数据库

实现这一点的最佳方式是什么


Tags: 对象方法实体框架idsfoo机构bar
2条回答

我能想到的最好的办法是:

var ids = new List<int>(){1,2,3,4,5,6,7};
var records = db.Records.Where(x=> ids.Contains(x.Id));
try
{
    foreach(var i in ids)
    {
        var record = records.FirstOrDefault(x=>x.Id == i);
        if(record == null)
        {
            throw new Exception($"Record with Id {i} not found");
        }
        record.Foo = "Bar";
    }
    db.saveChanges();
}
catch(Exception ex)
{
    //roll back changes
    var changedEntries = db.ChangeTracker.Entries()
    .Where(x => x.State != EntityState.Unchanged).ToList();
    foreach(var entry in changedEntries)
    {
        db.Entry(entry).State = EntityState.Unchanged;
    }
}

这里的理由是EF隐式地使用一个事务,当您调用.SaveChanges()时,该事务是“提交的”。如果出现问题,只需将实体的状态重置为“未更改”,并且从不调用SaveChanges()

^{}方法返回写入的条目数。
在更新的情况下,它将返回更新的行数

所以你想做的是:

  1. 启动新事务
  2. 对所有ID一起执行单个更新查询
  3. 检查返回值SaveChanges,如果它与查询中的ID数匹配,则检查返回值Commit,否则检查返回值Abort

相关问题 更多 >