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

10

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

var data= _dbContext.Set<ProductOrder>()
            .Where(c => c.ProductTypeId == this.productTypeId && c.saleYear == this.saleYear)
            .ToList();
使用Net Core 3.1连接SQL Server 2016数据库。

2
这与在“READ UNCOMMITTED”事务隔离级别下读取相同,因此在具有该隔离级别的事务下执行整个操作将产生相同的可怕影响。如果您需要结果正确,请不要在任何需要正确结果的地方使用NOLOCK;它可能会出现很多问题,并且可能会非常错误。请考虑替代方案,例如快照隔离。 - Jeroen Mostert
1个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
24
你可以像这样在EF Core中使用NOLOCK
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();
    }
}
更好的解决方案: 你可以创建一个扩展方法,用于创建一个带有“ReadUncommitted”状态的“TransactionScopeOption”。
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();
注意: 如果您想要为异步方法创建一个具有“ReadUnCommited”状态的事务,您应该在您的事务范围(TransactionScope)中使用“TransactionScopeAsyncFlowOption.Enabled”。
这个存储库对你来说可能会有帮助 Github。 更多信息:在EntityFramework中实现NOLOCK

10
在 TransactionScope 中是否需要使用 new 实例化一个 DbContext?这种情况下,在构造时注入 DbContext 给其他对象的情况下,这样做可能会出现问题。 - CSJ
当我使用以下代码时,即使没有DbContext,也能正常工作:new TransactionScope(scopeOption: TransactionScopeOption.Required, transactionOptions: new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted }, asyncFlowOption: TransactionScopeAsyncFlowOption.Enabled) - Sean
嗨,我正在尝试这个,但是当我检查EF生成的查询时,它没有"with(no lock)",应该有吧? - Johna
1
@Johna 没关系。但是在 sql 分析器中,你应该看到 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED - Farhad Zamani

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,