我正在尝试使用
NOLOCK
执行 EF Core 查询,有一篇文章演示了如何编写扩展方法,但它在 OData 查询中无法按预期工作。
这是链接: https://stackoverflow.com/a/63603655
query.ToListAsync
正在对表运行查询并尝试获取数百万条记录。而我正在尝试使用过滤器传递此查询
https://localhost:60484/odata/Users?$filter=userId eq 123&$expand=产品、订单
所以基本上,我试图从用户表中获取记录,其中
user id = 123
并且还想扩展产品和订单外键属性。
// Controller method
[HttpGet]
[EnableQuery]
public async Task<IQueryable<User>> Get()
{
return await _repository.UserRepository.GetUserData();
}
// Repository base
public async Task<List<T>> FindAll() => await _dbContext.Set<T>().AsNoTracking().ToListWithNoLockAsync();
// Repository method
public async Task<IQueryable<User>> GetUserData()
{
var data = await FindAll();
return data.AsQueryable()
.Include(a => a.Products)
.Include(a => a.Orders);
}
// Extension method from the article
public static class EFCoreTransaction
{
public static async Task<List<T>> ToListWithNoLockAsync<T>(
this IQueryable<T> query,
Expression<Func<T, bool>>? expression = null,
CancellationToken cancellationToken = default)
{
List<T>? result = default;
using (var scope = CreateTransaction())
{
if (expression != null)
{
query = query.Where(expression);
}
result = await query.ToListAsync(cancellationToken);
scope.Complete();
}
return result!;
}
private static TransactionScope CreateTransaction()
{
return new TransactionScope(TransactionScopeOption.Required,
new TransactionOptions()
{
IsolationLevel = IsolationLevel.ReadUncommitted
},
TransactionScopeAsyncFlowOption.Enabled);
}
}
我找到了一种方法来做到这一点。最终,我可以保持存储库类不变,只创建本文中提到的扩展类。 然后,在控制器中,我使用 ODataQueryOptions 进行了这些更改。由于 Iqueryable 实际上并不执行数据库查询,因此它将获取记录,然后在未提交读取的情况下应用 ToList() 。任何专家意见都会受到赞赏。我通过检查日志和 SQL 探查器对此进行了测试。生成的查询正在事务范围内运行。
[HttpGet]
[EnableQuery]
public async Task<IActionResult> Get(ODataQueryOptions<User> options)
{
IQueryable<User>? tempQuery = _repository.LeasedVendorsRepository.GetUserData();
IQueryable<User> result = tempQuery;
if (options.SelectExpand != null)
{
if (options.Filter != null)
{
tempQuery = options.Filter.ApplyTo(tempQuery, new ODataQuerySettings()) as IQueryable<User>;
}
result = (await tempQuery!.ToListWithNoLockAsync()).AsQueryable();
Request.ODataFeature().SelectExpandClause = options.SelectExpand.SelectExpandClause;
}
return Ok(result);
}