EF Core 2.0 TransactionScope Error

流过昼夜 提交于 2019-12-07 10:31:32

问题


I am trying to use TransactionScope in my SELECT query in EntityFramework Core 2.0. However I am getting this error : "Enlisting in Ambient transactions is not supported."

The idea is to implement "NO LOCK" option (I know it's not a good idea to have that option in place but it's vendor's requirement) when I do select query. So I added an extension method (Entity Framework with 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;
    }
}

And also I have set to ignore the Ambient Transaction Warning.

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

And I have the query as below in my repository

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();
}

I understood that .Net Core 2.0 supports TransactionScope. but I am not sure why I am getting this exception.

Any idea why is this happening?


回答1:


System.Transactions are not supported yet in EF Core. The issue is tracked by #5595: Enable support for System.Transactions and is committed to be included in the next EF Core release 2.1. (Update: EF Core 2.1 indeed added System.Transactions support).

Until then, if the whole point is to use transaction with ReadUncommitted, you can try using the explicit EF Core IDbTransaction through BeginTransaction(DatabaseFacade, IsolationLevel) extension method. Unfortunately it cannot be fully encapsulated like in your current custom extension method and requires passing the DbContext instance:

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;
    }
}



回答2:


I found a workaround that don't use transaction scopes for each query. If you run the code below, ef will use the same transaction isolation level for the same Server Process ID. Since Server Process ID does not change in same request, only one call for each request is sufficient.

this.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");


来源:https://stackoverflow.com/questions/46577551/ef-core-2-0-transactionscope-error

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!