C# 在EF Core中使用postgresql“SELECT FOR UPDATE”和linq-FromSqlRaw
我试图在EF核心中使用postgresql的行锁。我有一个.net核心应用程序和postgresql数据库 在GetUserContainer函数中,我使用FromSqlRaw构建查询,如下所示C# 在EF Core中使用postgresql“SELECT FOR UPDATE”和linq-FromSqlRaw,c#,.net,postgresql,entity-framework-core,rowlocking,C#,.net,Postgresql,Entity Framework Core,Rowlocking,我试图在EF核心中使用postgresql的行锁。我有一个.net核心应用程序和postgresql数据库 在GetUserContainer函数中,我使用FromSqlRaw构建查询,如下所示 var query = db.UserContainers.FromSqlRaw($"SELECT *, xmin FROM tableName {rowlock}") .Where(uc => uc.Id == id); 其中rowLock是一个函数参数,其值可以
var query = db.UserContainers.FromSqlRaw($"SELECT *, xmin FROM tableName {rowlock}")
.Where(uc => uc.Id == id);
其中rowLock是一个函数参数,其值可以用于更新或共享
我使用下面的代码来读取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");
}}));
根据代码和行锁概念,我预计第二个任务中的getusercontainer要么失败,要么等待行锁释放,因为它被第一个任务锁定
我正在尝试确保从应用程序端更新用户的ACID事务。
Postgresql文档清楚地表明,这在SQL中是可能的,但是我需要在C中实现这一点
有没有什么我做错了/遗漏了重要的细节?或者欢迎任何用新方法实现这一目标的建议。为什么要抛出异常?只需在用户选择和更新周围使用一个事务。这是单元测试方法,所以我试图断言第二个用户的更新失败,因为第一个用户锁定了行。然而,现在我放弃了使用FOR UPDATE锁定行的想法,而是依赖postgresql的xmin来确保并发检查。不幸的是,我不得不在EFCore:db.UserContainers.FromSqlRaw$SELECT*,xmin FROM tableName FOR UPDATE中重新使用FOR UPDATE。我相信从一周以来我一直在阅读的文档和大量的博客文章。然而,它们都是关于在数据库端执行FOR更新,而不是使用linq从应用程序端执行FOR更新。到目前为止,我已经被我读到的网络内容浸透了。以前有人这样做过吗?请帮助。为什么要抛出异常?只需在用户选择和更新周围使用一个事务。这是单元测试方法,所以我试图断言第二个用户的更新失败,因为第一个用户锁定了行。然而,现在我放弃了使用FOR UPDATE锁定行的想法,而是依赖postgresql的xmin来确保并发检查。不幸的是,我不得不在EFCore:db.UserContainers.FromSqlRaw$SELECT*,xmin FROM tableName FOR UPDATE中重新使用FOR UPDATE。我相信从一周以来我一直在阅读的文档和大量的博客文章。然而,它们都是关于在数据库端执行FOR更新,而不是使用linq从应用程序端执行FOR更新。到目前为止,我已经被我读到的网络内容浸透了。以前有人这样做过吗?请帮忙。
public UserContainer UpdateUserContainer(UserContainer item)
{
return db.UserContainers.Update(item).Entity;
}
public async Task Commit()
{
await db.SaveChangesAsync();
}