尽管先搜索,但在 SaveChanges 上出现唯一约束违规错误

问题描述 投票:0回答:1

我有一个 C# .NET 6.0 服务,其中添加了一个 OracleDbContext,Servicelifetime 为“Scoped”(据我所知,每个函数调用本质上都会获取自己的 DbContext 实例)。该服务在后台运行,并带有文件观察器,这样当文件被放入特定位置时,它将启动一些处理。首先,它查询数据库表以查看该文件的记录是否存在...如果不存在,那么它将尝试将记录插入到表中。

这是对存在性的检查,返回 null(文件名是主键):

_dbContext.[table].FirstOrDefault(ext => ext.FileName == fileName);

然后这是将被调用的插入函数,它甚至本身首先检查是否存在:

var existingRecord = _dbContext.[table]
               .FirstOrDefault(s => s.FileName == obj.FileName);

if (existingRecord != null)
{
    return true;
}

_dbContext.[table].Add(obj);
_dbContext.SaveChanges();

但是此服务运行一段时间后,我们最终会看到问题,它将到达 SaveChanges(),然后返回错误“ORA-00001:违反了唯一约束(EPADMIN.[主键约束])”。然而,记录已成功插入表中。当这种情况开始发生时,我们重新启动服务,并且通常会在一段时间内再次正常。 整个过程,除了服务本身的开始(服务启动时启动的功能)之外,都是同步的。数据库上下文确实配置了执行策略,因此它使用默认的事务隔离级别“已提交读”。有一次,我尝试为事务指定可序列化(在设置连接弹性之前),但这导致了它自己的问题。

我能做的是,当遇到该特定错误时,基本上只是忽略它并继续前进(因为记录在那里)。但这似乎是一种黑客方法——我担心一旦事情变得不正常,后续插入总是会返回该错误。我如何从一开始就防止他们失控,或者如果发生这种情况,基本上重置整个上下文?

我很乐意提供任何其他有帮助的详细信息。

c# database oracle entity-framework .net-core
1个回答
0
投票

多种方法之一是尝试将存在检查、插入和 SaveChanges 操作包装在事务中。这确保了操作是原子的,并防止使用相同的主键并发插入。

using var transaction = _dbContext.Database.BeginTransaction(); try { var existingRecord = _dbContext.[table].FirstOrDefault(s => s.FileName == obj.FileName); if (existingRecord == null) { _dbContext.[table].Add(obj); _dbContext.SaveChanges(); transaction.Commit(); } else { transaction.Rollback(); } } catch (Exception ex) { transaction.Rollback(); // Handle exceptions or log the error. }

© www.soinside.com 2019 - 2024. All rights reserved.