我试图在 EF Core 中使用 postgresql 的 ROW LOCK。我有一个 .net 核心应用程序和 postgresql 数据库。
在 GetUserContainer 函数中,我使用 FromSqlRaw 构建查询,如下所示
var query = db.UserContainers.FromSqlRaw($"SELECT *, xmin FROM tableName {rowlock}")
.Where(uc => uc.Id == id);
其中 rowLock 是一个函数参数,其值可以是“FOR UPDATE”或“FOR SHARE”。
我使用下面的代码来读取 UserContainers 并更新
await Task.WhenAll(
Task.Run(async () =>
{
using (var ctx = DbFixture.GetCtx()){
var repo = new PgUserRepository(ctx);
var usertoupdate = await repo.GetUserContainer(containerId,
dealershipId, eTag, true);
repo.UpdateUserContainer(usertoupdate, usertoupdate.eTag);
await repo.Commit();
}}),
Task.Run(async () =>
{
var message = await TypeOneChannel.Reader.WaitToReadAsync();
using (var ctx = DbFixture.GetCtx()){
var repo = new PgUserRepository(ctx);
repo.Invoking(async (userContainer) =>
await repo.GetUserContainer(containerId, dealershipId, eTag, true))
.Should()
.Throw<Exception>("Because the row is exclusively locked by other task");
}}));
注意:上面代码中用到的函数片段如下
public UserContainer UpdateUserContainer(UserContainer item)
{
return db.UserContainers.Update(item).Entity;
}
public async Task Commit()
{
await db.SaveChangesAsync();
}
根据代码和行锁概念,我希望第二个任务中的 getusercontainer 要么失败,要么等到行锁被释放,因为它被第一个任务锁定。
我试图确保从应用程序端更新用户的 ACID 事务。Postgresql 文档 ( ROW LOCK ) 清楚地表明它在 SQL 中是可能的,但是我需要在 C# 中实现它。
我做错了什么/遗漏了重要的细节吗?或者欢迎任何通过新方法实现这一目标的建议。