使用实体框架锁定选定的sql资源

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

我正在尝试使用实体框架编写一个

SELECT... FOR UPDATE
查询(对于
Postgresql
数据库)。问题是,使用任何
IsolationLevel
,第二个请求只会在更新数据后阻塞(图中的步骤 2),而不是从第一个请求(获取图中的响应步骤)开始阻塞。
Chaos
不支持级别(不知道为什么)。

即使从选择中我也需要锁定资源,否则两个请求将占用相同的资源!

我找不到使用 EF 的解决方案,但这可以使用 SQL 函数(+迁移),这不是首选!

谢谢

// Serializable Summary
//     A range lock is placed on the System.Data.DataSet, preventing other users from
//     updating or inserting rows into the dataset until the transaction is complete.

await using var transaction = await _dbContext.Database.BeginTransactionAsync(
    System.Data.IsolationLevel.Serializable,
    cancellationToken);

try
{
    var query = _dbContext.ValidationRequests
            .Where(vr => vr.State == Statuses.New)
            .OrderBy(vr => vr.Id);

    var response = await PagedList<Model>.GetPagedListAsync(
        query,
        page,
        pageSize,
        cancellationToken
    );

    await UpdateRangeAsync(response.Items, cancellationToken);

    await transaction.CommitAsync(cancellationToken);

    return response;
}
catch (Exception)
{
    await transaction.RollbackAsync(cancellationToken);

    throw;
}

以及更新方法:

private async Task UpdateRangeAsync(List<Model> requests, CancellationToken cancellationToken = default)
{
    if (!requests.Any())
    {
        return;
    }

    requests.ForEach(item => item.State = Statuses.Pending);

    _dbContext.UpdateRange(requests);
    await _dbContext.SaveChangesAsync(cancellationToken);
}
.net entity-framework locking
1个回答
0
投票

您可以使用新的

ExecuteUpdateAsync
功能来执行连接的
UPDATE
语句。这意味着您不需要事务,因为无论如何整个语句都是原子的。

这样的东西会起作用,尽管我不完全清楚你的对象模型。

var baseQuery = PagedList<Model>
    .Where(pl => pl.ValidationRequests
        .Any(vr => vr.State == Statuses.New)
);

await baseQuery.ExecuteUpdateAsync(setters => setters
    .SetProperty(item => item.State, Statuses.Pending,
    cancellationToken);
© www.soinside.com 2019 - 2024. All rights reserved.