Entity Framework Core:使用 NOLOCK 读取和选择记录

Posted

技术标签:

【中文标题】Entity Framework Core:使用 NOLOCK 读取和选择记录【英文标题】:Entity Framework Core: Read and Select Records using NOLOCK 【发布时间】:2020-12-15 14:24:33 【问题描述】:

如何使用 NOLOCK 在 Entity Framework Core 中读取/选择一个? (以避免 OLTP 数据库中的锁定/阻塞/死锁)。 这是一个示例选择查询。

var data= _dbContext.Set<ProductOrder>()
            .Where(c => c.ProductTypeId == this.productTypeId && c.saleYear == this.saleYear)
            .ToList();

将 Net Core 3.1 与 SQL Server 2016 数据库结合使用。

【问题讨论】:

这与在READ UNCOMMITTED事务隔离级别下读取相同,因此在具有该隔离级别的事务下执行整个操作将具有相同的可怕效果。不要使用NOLOCK,如果您可以帮助您实际需要结果正确的任何事情;有so many ways 可以去very wrong。考虑替代方案,例如快照隔离。 【参考方案1】:

您可以像这样使用NOLOCKEF Core

using (new TransactionScope(TransactionScopeOption.Required, new TransactionOptions

    IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted
))

    using (var db = new YourDbContext())
    
        var data = db.Set<ProductOrder>()
            .Where(c => c.ProductTypeId == this.productTypeId && c.saleYear == this.saleYear)
            .ToList();
    

更好的解决方案:

您可以创建一个扩展方法来创建TransactionScopeOptionReadUncommitted 状态:

public static async Task<List<T>> ToListWithNoLockAsync<T>(this IQueryable<T> query, CancellationToken cancellationToken = default, Expression<Func<T, bool>> expression = null)

    List<T> result = default;
    using (var scope = CreateTrancation())
    
        if (expression != null)
        
            query = query.Where(expression);
        
        result = await query.ToListAsync(cancellationToken);
        scope.Complete();
    
    return result;

private static TransactionScope CreateTrancation()

    return new TransactionScope(TransactionScopeOption.Required,
                                new TransactionOptions()
                                
                                    IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted
                                ,
                               TransactionScopeAsyncFlowOption.Enabled);

用法:

var categories = dbContext.Categories
                          .AsNoTracking()
                          .Where(a => a.IsDelete == false)
                          .ToListWithNoLockAsync();

注意:

如果您想为async 方法创建具有ReadUnCommited 状态的事务,您应该在TransactionScope 中使用TransactionScopeAsyncFlowOption.Enabled


这个仓库对你有帮助Github

【讨论】:

是否需要new TransactionScope 内的 DbContext?在构建时将 DbContext 注入其他事物的情况下,这将无法正常工作... 在没有 DbContext 的情况下为我工作:new TransactionScope(scopeOption: TransactionScopeOption.Required, transactionOptions: new TransactionOptions IsolationLevel = IsolationLevel.ReadUncommitted , asyncFlowOption: TransactionScopeAsyncFlowOption.Enabled)

以上是关于Entity Framework Core:使用 NOLOCK 读取和选择记录的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework Core 性能优化

在 Entity Framework Core 中使用 [ComplexType]

在 Entity Framework Core 中使用 SQL 视图

使用 Entity Framework Core 更新相关数据

使用 Entity Framework Core 自动增加部分主键

如何使用 Entity Framework Core 模拟异步存储库