4

我正在尝试在 EntityFramework Core 2.0 的 SELECT 查询中使用 TransactionScope。但是我收到此错误:“不支持在环境事务中登记。”

这个想法是在我选择查询时实现“NO LOCK”选项(我知道拥有该选项不是一个好主意,但这是供应商的要求)。所以我添加了一个扩展方法(带有 NOLOCK 的实体框架

public static async Task<List<T>> ToListReadUncommittedAsync<T>(this IQueryable<T> query)
{
    using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew,
        new TransactionOptions()
        {
            IsolationLevel = IsolationLevel.ReadUncommitted
        }, TransactionScopeAsyncFlowOption.Enabled))
    {
        var result = await query.ToListAsync();
        scope.Complete();
        return result;
    }
}

而且我已经设置忽略环境事务警告。

public static void AddEntityFramework(this IServiceCollection services, string connectionString)
{
    services.AddDbContextPool<OptomateContext>(options =>
    {
        options.UseSqlServer(connectionString);
        options.ConfigureWarnings(x => x.Ignore(RelationalEventId.AmbientTransactionWarning));
    });
}

我的存储库中有如下查询

public async Task<Patient> GetPatient(Common.Resources.Patient patient)
{
    var pat = await Dbset.Where(x => string.Equals(x.Surname,patient.Surname, 
    StringComparison.CurrentCultureIgnoreCase)).ToListReadUncommittedAsync();                                    

    return pat.FirstOrDefault();
}

我了解 .Net Core 2.0 支持 TransactionScope。但我不确定为什么会收到此异常。

知道为什么会这样吗?

4

2 回答 2

8

System.TransactionsEF Core 尚不支持。该问题由#5595: Enable support for System.Transactions跟踪,并承诺包含在下一个 EF Core 版本 2.1中。(更新: EF Core 2.1 确实添加了 System.Transactions 支持)。

在那之前,如果重点是使用事务,您可以尝试通过扩展方法ReadUncommitted使用显式 EF Core 。不幸的是,它不能像您当前的自定义扩展方法那样完全封装,并且需要传递实例:IDbTransactionBeginTransaction(DatabaseFacade, IsolationLevel)DbContext

public static async Task<List<T>> ToListReadUncommittedAsync<T>(this IQueryable<T> query, DbContext context)
{
    using (var transaction = await context.Database.BeginTransactionAsync(System.Data.IsolationLevel.ReadUncommitted))           {
    {
        var result = await query.ToListAsync();
        transaction.Commit();
        return result;
    }
}
于 2017-10-05T09:36:43.720 回答
0

我找到了一个不为每个查询使用事务范围的解决方法。如果你运行下面的代码,ef 将对相同的服务器进程 ID 使用相同的事务隔离级别。由于服务器进程 ID 在同一请求中不会更改,因此每个请求只需调用一次就足够了。

this.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");
于 2018-03-06T14:54:33.807 回答