Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass current transaction to DbCommand

I'm working on a project using ASP.NET Core 2.1 and EF Core 2.1. Although most of queries and commands use EF, some units needs to call stored procedures directly.

I can't use FromSql, because it needs results set based on entity models.

Let's assume we have these methods:

public Task CommandOne(DbContext context)
{
    Entity entity = new Entity
    {
        Name = "Name"
    };

    context.DbSet<Entity>().Add(entity);

    return context.SaveChangesAsync();
}

public async Task CommandTwo(DbContext context)
{
    DbCommand command = context.Database.GetDbConnection().CreateCommand();
    command.CommandText = "storedProcName";
    command.CommandType = System.Data.CommandType.StoredProcedure;

    using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false))
    {
        // read result sets
    }
}

If I call both commands in one transaction like this:

public async Task UnitOfWork(DbContext dbContext)
{
    using (var transaction = await dbContext.Database.BeginTransactionAsync())
    {
        await CommandOne(dbContext);
        await CommandTwo(dbContext);
    }
}

This exception happens:

BeginExecuteReader requires the command to have a transaction when the connection assigned to the command is in a pending local transaction. The Transaction property of the command has not been initialized.

I have to mention, it's not as simple as command.Transaction = .... This requires DbTransaction which differs from the transaction EF uses.

I've been stuck with this for a month!

Is there any workaround for this?

Thank you so much.

like image 810
Mohammad Azhdari Avatar asked Sep 16 '18 09:09

Mohammad Azhdari


People also ask

Does EF core use transaction?

EF Core relies on database providers to implement support for System. Transactions. If a provider does not implement support for System.

Does Entity Framework support transactions?

In all versions of Entity Framework, whenever you execute SaveChanges() to insert, update or delete on the database the framework will wrap that operation in a transaction. This transaction lasts only long enough to execute the operation and then completes.

Does SaveChanges commit?

In Entity Framework, the SaveChanges() method internally creates a transaction and wraps all INSERT, UPDATE and DELETE operations under it. Multiple SaveChanges() calls, create separate transactions, perform CRUD operations and then commit each transaction.


1 Answers

I have to mention, it's not as simple as command.Transaction = .... This requires DbTransaction which differs from the transaction EF uses.

Actually it is. All you need is a reference to Microsoft.EntityFrameworkCore.Relational assembly and add

using Microsoft.EntityFrameworkCore.Storage;

to get access to GetDbTransaction extension method:

command.Transaction = context.Database.CurrentTransaction?.GetDbTransaction();
like image 111
Ivan Stoev Avatar answered Oct 08 '22 23:10

Ivan Stoev