Efcore: In Entity Framework Core 1.0.0-RC2-Final, there seems to be no way to get the underlying DBTransaction after invoking Db.Database.BeingTransaction()

Created on 26 May 2016  路  3Comments  路  Source: dotnet/efcore

In RC1, given a DbContext instance, it was possible to begin a new transaction and gain access to the underlying DbTransaction in the following manner:

using (var transaction = dbContext.Database.BeginTransaction())
{
var dbTransaction = transaction.Instance;
//do other stuff
dbContext.SaveChanges();
dbContext.Database.CommitTransaction();
}

Having easy access to the underlying DbTransaction is quite useful when it is desirable to do Entity Framework persistence in the same transaction as straight ADO.NET persistence (bulk insert, for example).

In RC2, BeginTransaction() now returns an instance of IDbContextTransaction, which does not provide a property or method to get the underlying DbTransaction instance. The only way I was able to work around this was to first create the transaction from the DBContext's DbConnection, explicitly open the connection, begin a new transaction using that connection and then tell the DbContext to use that transaction, as follows:

using (var connection = Db.Database.GetDbConnection())
{
if (connection.State == System.Data.ConnectionState.Closed)
{
connection.Open();
}
using (var transaction = connection.BeginTransaction())
{
Db.Database.UseTransaction(transaction);
// do other stuff
Db.SaveChanges();
transaction.Commit();
}
}

This seems significantly more convoluted and error prone than it was in RC1. Perhaps there is already a way to get a DbTransaction from the DbContext that I have not been able to discover, but if not, would it be feasible to enhance IDbContextTransaction to expose it?

Most helpful comment

@pachecosoftware if you add a using Microsoft.EntityFrameworkCore.Storage then you will get a GetDbTransaction() extension method on IDbContextTransaction. It's an extension method now, because we promoted transactions to be part of the core of EF, but DbTransaction is specific to relational data stores.

All 3 comments

@pachecosoftware if you add a using Microsoft.EntityFrameworkCore.Storage then you will get a GetDbTransaction() extension method on IDbContextTransaction. It's an extension method now, because we promoted transactions to be part of the core of EF, but DbTransaction is specific to relational data stores.

Thanks so much for getting back with me. Your explanation of why it moved to an extension method makes sense and adding the using statement worked just as you indicated.

As a follow-up question, once a transaction has begun, is there any way to determine if a DbContext is currently in the context of a transaction? It appears that DatabaseFacade and the underlying IDbContextTransactionManager it wraps only expose methods to begin, commit or rollback a transaction, so I assume this is not possible, but was hoping that perhaps I'm missing something.

Looks like we don't have an API to get the current transaction at the moment. I've opened https://github.com/aspnet/EntityFramework/issues/5552 to make sure we add one (it will be post-RTM thought).

Was this page helpful?
0 / 5 - 0 ratings