0

我有一个表在一些批量更新期间有一些潜在的锁。我正在使用 SqlServer。

我想允许对这一特定的读取操作进行脏读。这看起来像正确的实现吗?是否有另一种方法可以为某个特定操作启用 [WITH NOLOCK]?

不幸的是,我找不到关于该主题的太多文档,希望提供任何包含更多信息的链接。

以这种方式使用交易是否有任何潜在的失败?

此外,是否有任何方法可以在所有操作的上下文中启用脏读?

        public async Task<AppUser> GetUserByIdAsync(string employeeId)
        {

            using var transaction = await _context.Database.BeginTransactionAsync(System.Data.IsolationLevel.ReadUncommitted);
            
            var users =  await _context.Users
                .Include(u => u.PositionRoles)
                .ThenInclude(p => p.Role)
                .Include(u => u.UserRoles)
                .ThenInclude(r => r.Role)
                .Include(u => u.TeamRoles)
                .ThenInclude(r => r.Role)
                .Include(u => u.UserLocations)
                .SingleOrDefaultAsync(u => u.EmployeeId == employeeId);

            await transaction.DisposeAsync();

            return users;
        }
4

1 回答 1

0

EF Core 拦截器非常适合您的任务。

您可以查看文档他们如何修改命令(SQL 查询)并思考如何应用DbCommandInterceptor.WithTag获取特定操作的未提交读取。

对于上下文上的全局脏读,DbConnectionInterceptor看起来不错。
这个在我的测试中有效

class ConnectionInterceptor : DbConnectionInterceptor
{
    public override void ConnectionOpened(DbConnection connection, ConnectionEndEventData eventData)
    {
        var command = connection.CreateCommand();
        command.CommandText = "SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED";
        command.ExecuteNonQuery();
        base.ConnectionOpened(connection, eventData);
    }

    public override InterceptionResult ConnectionClosing(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)
    {
        var command = connection.CreateCommand();
        //Set default isolation level here
        command.CommandText = "SET TRANSACTION ISOLATION LEVEL READ COMMITTED";
        command.ExecuteNonQuery();
        return base.ConnectionClosing(connection, eventData, result);
    }
}
于 2021-07-04T20:56:42.073 回答