Browse Source

Fixed #8049: UnitOfWorkDbContextProvider should not reuse the transaction if dbcontext doesn't reuse the connection.

pull/8170/head
Halil İbrahim Kalkan 5 years ago
parent
commit
5d1fb4e434
  1. 2
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/DbContextCreationContext.cs
  2. 10
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/EfCoreTransactionApi.cs
  3. 46
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/UnitOfWorkDbContextProvider.cs

2
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/DbContextCreationContext.cs

@ -13,7 +13,7 @@ namespace Volo.Abp.EntityFrameworkCore.DependencyInjection
public string ConnectionString { get; }
public DbConnection ExistingConnection { get; set; }
public DbConnection ExistingConnection { get; internal set; }
public DbContextCreationContext(string connectionStringName, string connectionString)
{

10
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/EfCoreTransactionApi.cs

@ -34,9 +34,10 @@ namespace Volo.Abp.Uow.EntityFrameworkCore
foreach (var dbContext in AttendedDbContexts)
{
if (dbContext.As<DbContext>().HasRelationalTransactionManager())
if (dbContext.As<DbContext>().HasRelationalTransactionManager() &&
dbContext.Database.GetDbConnection() == DbContextTransaction.GetDbTransaction().Connection)
{
continue; //Relational databases use the shared transaction
continue; //Relational databases use the shared transaction if they are using the same connection
}
await dbContext.Database.CommitTransactionAsync(CancellationTokenProvider.Token);
@ -54,9 +55,10 @@ namespace Volo.Abp.Uow.EntityFrameworkCore
foreach (var dbContext in AttendedDbContexts)
{
if (dbContext.As<DbContext>().HasRelationalTransactionManager())
if (dbContext.As<DbContext>().HasRelationalTransactionManager() &&
dbContext.Database.GetDbConnection() == DbContextTransaction.GetDbTransaction().Connection)
{
continue; //Relational databases use the shared transaction
continue; //Relational databases use the shared transaction if they are using the same connection
}
await dbContext.Database.RollbackTransactionAsync(CancellationTokenProvider.FallbackToProvider(cancellationToken));

46
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/UnitOfWorkDbContextProvider.cs

@ -105,6 +105,7 @@ namespace Volo.Abp.Uow.EntityFrameworkCore
return (TDbContext)((EfCoreDatabaseApi)databaseApi).DbContext;
}
[Obsolete("Use CreateDbContextAsync method.")]
private TDbContext CreateDbContext(IUnitOfWork unitOfWork, string connectionStringName, string connectionString)
{
var creationContext = new DbContextCreationContext(connectionStringName, connectionString);
@ -145,6 +146,7 @@ namespace Volo.Abp.Uow.EntityFrameworkCore
}
}
[Obsolete("Use CreateDbContextAsync.")]
private TDbContext CreateDbContext(IUnitOfWork unitOfWork)
{
return unitOfWork.Options.IsTransactional
@ -159,6 +161,7 @@ namespace Volo.Abp.Uow.EntityFrameworkCore
: unitOfWork.ServiceProvider.GetRequiredService<TDbContext>();
}
[Obsolete("Use CreateDbContextWithTransactionAsync.")]
private TDbContext CreateDbContextWithTransaction(IUnitOfWork unitOfWork)
{
var transactionApiKey = $"EntityFrameworkCore_{DbContextCreationContext.Current.ConnectionString}";
@ -191,7 +194,24 @@ namespace Volo.Abp.Uow.EntityFrameworkCore
if (dbContext.As<DbContext>().HasRelationalTransactionManager())
{
dbContext.Database.UseTransaction(activeTransaction.DbContextTransaction.GetDbTransaction());
if (dbContext.Database.GetDbConnection() == DbContextCreationContext.Current.ExistingConnection)
{
dbContext.Database.UseTransaction(activeTransaction.DbContextTransaction.GetDbTransaction());
}
else
{
/* User did not re-use the ExistingConnection and we are starting a new transaction.
* EfCoreTransactionApi will check the connection string match and separately
* commit/rollback this transaction over the DbContext instance. */
if (unitOfWork.Options.IsolationLevel.HasValue)
{
dbContext.Database.BeginTransaction(unitOfWork.Options.IsolationLevel.Value);
}
else
{
dbContext.Database.BeginTransactionAsync();
}
}
}
else
{
@ -239,7 +259,29 @@ namespace Volo.Abp.Uow.EntityFrameworkCore
if (dbContext.As<DbContext>().HasRelationalTransactionManager())
{
await dbContext.Database.UseTransactionAsync(activeTransaction.DbContextTransaction.GetDbTransaction(), GetCancellationToken());
if (dbContext.Database.GetDbConnection() == DbContextCreationContext.Current.ExistingConnection)
{
await dbContext.Database.UseTransactionAsync(activeTransaction.DbContextTransaction.GetDbTransaction(), GetCancellationToken());
}
else
{
/* User did not re-use the ExistingConnection and we are starting a new transaction.
* EfCoreTransactionApi will check the connection string match and separately
* commit/rollback this transaction over the DbContext instance. */
if (unitOfWork.Options.IsolationLevel.HasValue)
{
await dbContext.Database.BeginTransactionAsync(
unitOfWork.Options.IsolationLevel.Value,
GetCancellationToken()
);
}
else
{
await dbContext.Database.BeginTransactionAsync(
GetCancellationToken()
);
}
}
}
else
{

Loading…
Cancel
Save