从 table 到 Entity Framework Core 的条目(检索和删除)的隔离事务?

An isolated transaction to (retrieve and delete) an entry from a table through Entity Framework Core?

为了形象化——天真地——如果我想完成这样的操作,我可能会使用下面的代码。

假设 dbContextdbContext.Entries 分别属于 DbContext (PostgreSQL) 和 DbSet<Entry> 类型。

var entry = await dbContext.Entries.FindAsync(key);
dbContext.Entries.Remove(entry);
await dbContext.SaveChangesAsync();
return entry;

但是,如果这段代码是由两个或多个进程并发执行的,我认为它可能不是完全隔离的(如果我错了请指正)。例如,两个进程首先从第一行接收相同的条目,然后将其删除。尽管该条目仍将被正确删除,但两个进程都会收到该条目,这违反了隔离规则。

我想知道是否可以使用 EF Core 来处理这种情况,以便每个事务都与其他事务完全隔离?

我从研究中发现的一种方法是用显式事务语句(docs) and change the isolation level if needed. However, from the docs of DbSet.FindAsync(),如果“给定的”,则不会对数据库进行查询上下文正在跟踪主键值。"

而且我不确定 DbSet.FindAsync() 操作是否会像修改操作(例如 DbSet.Remove()DbSet.Add())一样在明确声明的事务中按顺序考虑。

如果我的任何假设有误,请纠正我,在此先感谢!

编辑:抱歉提及;我将 PostgreSQL 与 EF Core 结合使用。

如果 entity framework 尝试修改或删除丢失或最近更新的记录,它将抛出 DbUpdateConcurrencyException

DbUpdateConcurrencyException Exception thrown by DbContext when it was expected that SaveChanges for an entity would result in a database update but in fact no rows in the database were affected. This usually indicates that the database has been concurrently updated such that a concurrency token that was expected to match did not actually match

因此您可以将代码包装在 try catch 中并捕获该异常。

try
{
   var entry = await dbContext.Entries.FindAsync(key);
   dbContext.Entries.Remove(entry);
   await dbContext.SaveChangesAsync();
   return entry;
}
catch(DbUpdateConcurrencyException e)
{
   // do something with e
}
catch(Exception e)
{
   // if something else happens, like null reference
}