Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF Core 2.0 TransactionScope Error

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?

like image 394
Alan B Avatar asked Jan 30 '23 11:01

Alan B


1 Answers

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;
    }
}
like image 137
Ivan Stoev Avatar answered Feb 02 '23 11:02

Ivan Stoev