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