通过实体框架核心从表中(检索和删除)条目的独立事务



如果我想完成这样的操作,我可能会使用下面的代码来直观地显示。

假设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(封装这段代码,并在需要时更改隔离级别。然而,从DbSet.FindAsync()的文档中,如果";上下文正在跟踪给定的主键值">

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

如果我的任何假设是错误的,请纠正我,并提前感谢!

编辑:很抱歉提及;我使用带有EF Core的PostgreSQL。

如果实体框架试图修改或删除丢失或最近更新的记录,它将抛出DbUpdateConcurrencyException

DbUpdateConcurrencyException当预期实体的SaveChanges将导致数据库更新,但实际上数据库中没有行受到影响时,DbContext引发异常。这通常表示数据库已同时更新,因此预期匹配的并发令牌实际上与不匹配

因此,您可以将代码封装在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
}

最新更新