mirror of https://github.com/abpframework/abp.git
15 changed files with 282 additions and 32 deletions
@ -0,0 +1,14 @@ |
|||
using Microsoft.EntityFrameworkCore.Infrastructure; |
|||
using Microsoft.EntityFrameworkCore.Storage; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.EntityFrameworkCore |
|||
{ |
|||
public static class DatabaseFacadeExtensions |
|||
{ |
|||
public static bool IsRelational(this DatabaseFacade database) |
|||
{ |
|||
return database.GetInfrastructure().GetService<IRelationalConnection>() != null; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore.Infrastructure; |
|||
using Microsoft.EntityFrameworkCore.Storage; |
|||
|
|||
namespace Volo.Abp.EntityFrameworkCore |
|||
{ |
|||
internal static class DbContextExtensions |
|||
{ |
|||
public static bool HasRelationalTransactionManager(this DbContext dbContext) |
|||
{ |
|||
return dbContext.Database.GetService<IDbContextTransactionManager>() is IRelationalTransactionManager; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
using System.Data; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore.Storage; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.EntityFrameworkCore; |
|||
using Volo.Abp.EntityFrameworkCore.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Uow.EntityFrameworkCore |
|||
{ |
|||
public class DbContextEfCoreTransactionStrategy : IEfCoreTransactionStrategy, ITransientDependency |
|||
{ |
|||
public TDbContext CreateDbContext<TDbContext>(IUnitOfWork unitOfWork, DbContextCreationContext creationContext) where TDbContext : DbContext |
|||
{ |
|||
var transactionApiKey = $"EntityFrameworkCore_{creationContext.ConnectionString}"; |
|||
var activeTransaction = unitOfWork.FindTransactionApi(transactionApiKey) as IEfCoreTransactionApi; |
|||
|
|||
TDbContext dbContext; |
|||
if (activeTransaction == null) |
|||
{ |
|||
dbContext = unitOfWork.ServiceProvider.GetRequiredService<TDbContext>(); |
|||
var dbtransaction = dbContext.Database.BeginTransaction((unitOfWork.Options.IsolationLevel ?? IsolationLevel.ReadUncommitted)); |
|||
activeTransaction = new EfCoreTransactionApi(dbtransaction, dbContext); |
|||
unitOfWork.AddTransactionApi(transactionApiKey, activeTransaction); |
|||
} |
|||
else |
|||
{ |
|||
creationContext.ExistingConnection = activeTransaction.DbContextTransaction.GetDbTransaction().Connection; |
|||
dbContext = unitOfWork.ServiceProvider.GetRequiredService<TDbContext>(); |
|||
|
|||
if (dbContext.HasRelationalTransactionManager()) |
|||
{ |
|||
dbContext.Database.UseTransaction(activeTransaction.DbContextTransaction.GetDbTransaction()); |
|||
} |
|||
else |
|||
{ |
|||
dbContext.Database.BeginTransaction(); |
|||
} |
|||
|
|||
activeTransaction.AttendedDbContexts.Add(dbContext); |
|||
} |
|||
|
|||
return dbContext; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore.Storage; |
|||
using Volo.Abp.EntityFrameworkCore; |
|||
|
|||
namespace Volo.Abp.Uow.EntityFrameworkCore |
|||
{ |
|||
public class EfCoreTransactionApi : IEfCoreTransactionApi |
|||
{ |
|||
public IDbContextTransaction DbContextTransaction { get; } |
|||
public DbContext StarterDbContext { get; } |
|||
public List<DbContext> AttendedDbContexts { get; } |
|||
|
|||
public EfCoreTransactionApi(IDbContextTransaction dbContextTransaction, DbContext starterDbContext) |
|||
{ |
|||
DbContextTransaction = dbContextTransaction; |
|||
StarterDbContext = starterDbContext; |
|||
AttendedDbContexts = new List<DbContext>(); |
|||
} |
|||
|
|||
public void Commit() |
|||
{ |
|||
DbContextTransaction.Commit(); |
|||
|
|||
foreach (var dbContext in AttendedDbContexts) |
|||
{ |
|||
if (dbContext.HasRelationalTransactionManager()) |
|||
{ |
|||
continue; //Relational databases use the shared transaction
|
|||
} |
|||
|
|||
dbContext.Database.CommitTransaction(); |
|||
} |
|||
} |
|||
|
|||
public Task CommitAsync() |
|||
{ |
|||
Commit(); |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
DbContextTransaction.Dispose(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
using System.Collections.Generic; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore.Storage; |
|||
|
|||
namespace Volo.Abp.Uow.EntityFrameworkCore |
|||
{ |
|||
public interface IEfCoreTransactionApi : ITransactionApi |
|||
{ |
|||
IDbContextTransaction DbContextTransaction { get; } |
|||
|
|||
DbContext StarterDbContext { get; } |
|||
|
|||
List<DbContext> AttendedDbContexts { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Volo.Abp.EntityFrameworkCore.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Uow.EntityFrameworkCore |
|||
{ |
|||
public interface IEfCoreTransactionStrategy |
|||
{ |
|||
TDbContext CreateDbContext<TDbContext>(IUnitOfWork unitOfWork, DbContextCreationContext creationContext) |
|||
where TDbContext : DbContext; |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Volo.Abp.Uow |
|||
{ |
|||
public interface ITransactionApi |
|||
{ |
|||
void Commit(); |
|||
|
|||
Task CommitAsync(); |
|||
|
|||
void Dispose(); |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.Uow |
|||
{ |
|||
public interface ITransactionApiContainer |
|||
{ |
|||
[CanBeNull] |
|||
ITransactionApi FindTransactionApi([NotNull] string key); |
|||
|
|||
void AddTransactionApi([NotNull] string key, [NotNull] ITransactionApi api); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue