diff --git a/Build/Build.cs b/Build/Build.cs index e4b0e215..f95fede8 100644 --- a/Build/Build.cs +++ b/Build/Build.cs @@ -135,7 +135,7 @@ protected override void OnBuildInitialized() { Log.Information("Generating NuGet packages for projects in solution"); int commitNum = 0; - string NuGetVersionCustom = "2.0.0.880"; + string NuGetVersionCustom = "2.0.0.881"; //if it's not a tagged release - append the commit number to the package version diff --git a/Examples/CleanWithCQRS/HR.LeaveManagement.Persistence/AuditableDbContext.cs b/Examples/CleanWithCQRS/HR.LeaveManagement.Persistence/AuditableDbContext.cs index 47ae4dc1..4d66f242 100644 --- a/Examples/CleanWithCQRS/HR.LeaveManagement.Persistence/AuditableDbContext.cs +++ b/Examples/CleanWithCQRS/HR.LeaveManagement.Persistence/AuditableDbContext.cs @@ -17,9 +17,8 @@ public abstract class AuditableDbContext : RCommonDbContext private readonly ICurrentUser _currentUser; private readonly ISystemTime _systemTime; - public AuditableDbContext(DbContextOptions options, ICurrentUser currentUser, ISystemTime systemTime, - IEntityEventTracker eventTracker) - : base(options, eventTracker) + public AuditableDbContext(DbContextOptions options, ICurrentUser currentUser, ISystemTime systemTime) + : base(options) { _currentUser = currentUser; this._systemTime = systemTime; @@ -51,10 +50,5 @@ public override Task SaveChangesAsync(bool acceptAllChangesOnSuccess, Cance return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); } - - public override async Task PersistChangesAsync() - { - await base.PersistChangesAsync(); - } } } diff --git a/Examples/CleanWithCQRS/HR.LeaveManagement.Persistence/LeaveManagementDbContext.cs b/Examples/CleanWithCQRS/HR.LeaveManagement.Persistence/LeaveManagementDbContext.cs index 45aa33e7..932a9d53 100644 --- a/Examples/CleanWithCQRS/HR.LeaveManagement.Persistence/LeaveManagementDbContext.cs +++ b/Examples/CleanWithCQRS/HR.LeaveManagement.Persistence/LeaveManagementDbContext.cs @@ -15,9 +15,8 @@ namespace HR.LeaveManagement.Persistence public class LeaveManagementDbContext : AuditableDbContext { - public LeaveManagementDbContext(DbContextOptions options, ICurrentUser currentUser, ISystemTime systemTime, - IEntityEventTracker eventTracker) - : base(options, currentUser, systemTime, eventTracker) + public LeaveManagementDbContext(DbContextOptions options, ICurrentUser currentUser, ISystemTime systemTime) + : base(options, currentUser, systemTime) { } diff --git a/Src/RCommon.Dapper/Crud/DapperRepository.cs b/Src/RCommon.Dapper/Crud/DapperRepository.cs index 8b2cc215..c7fbcb47 100644 --- a/Src/RCommon.Dapper/Crud/DapperRepository.cs +++ b/Src/RCommon.Dapper/Crud/DapperRepository.cs @@ -25,10 +25,10 @@ public class DapperRepository : SqlRepositoryBase where TEntity : class, IBusinessEntity { - public DapperRepository(IDataStoreRegistry dataStoreRegistry, IDataStoreEnlistmentProvider dataStoreEnlistmentProvider, - ILoggerFactory logger, IUnitOfWorkManager unitOfWorkManager, IEntityEventTracker eventTracker, + public DapperRepository(IDataStoreFactory dataStoreFactory, + ILoggerFactory logger, IEntityEventTracker eventTracker, IOptions defaultDataStoreOptions) - : base(dataStoreRegistry, dataStoreEnlistmentProvider, logger, unitOfWorkManager, eventTracker, defaultDataStoreOptions) + : base(dataStoreFactory, logger, eventTracker, defaultDataStoreOptions) { Logger = logger.CreateLogger(GetType().Name); } @@ -48,7 +48,6 @@ public override async Task AddAsync(TEntity entity, CancellationToken token = de await db.InsertAsync(entity, cancellationToken: token); entity.AddLocalEvent(new EntityCreatedEvent(entity)); EventTracker.AddEntity(entity); - await DispatchEvents(); } catch (ApplicationException exception) @@ -82,7 +81,6 @@ public override async Task DeleteAsync(TEntity entity, CancellationToken token = await db.DeleteAsync(entity, cancellationToken: token); entity.AddLocalEvent(new EntityDeletedEvent(entity)); EventTracker.AddEntity(entity); - await DispatchEvents(); } catch (ApplicationException exception) { @@ -117,7 +115,6 @@ public override async Task UpdateAsync(TEntity entity, CancellationToken token = await db.UpdateAsync(entity, cancellationToken: token); entity.AddLocalEvent(new EntityUpdatedEvent(entity)); EventTracker.AddEntity(entity); - await DispatchEvents(); } catch (ApplicationException exception) { @@ -316,23 +313,6 @@ public override async Task AnyAsync(ISpecification specification, return await AnyAsync(specification.Predicate, token); } - protected async Task DispatchEvents() - { - try - { - if (!UnitOfWorkManager.IsUnitOfWorkActive) - { - Guard.Against(DataStore == null, "DataStore is null"); - await DataStore.PersistChangesAsync(); // This dispatches the events - } - } - catch (ApplicationException exception) - { - Logger.LogError(exception, "Error in {0}.DispatchEvents while executing on the Context.", GetType().FullName); - throw; - } - } - } } diff --git a/Src/RCommon.Dapper/DapperPersistenceBuilder.cs b/Src/RCommon.Dapper/DapperPersistenceBuilder.cs index c7517e00..d3ad8273 100644 --- a/Src/RCommon.Dapper/DapperPersistenceBuilder.cs +++ b/Src/RCommon.Dapper/DapperPersistenceBuilder.cs @@ -10,6 +10,7 @@ using Microsoft.Extensions.DependencyInjection; using RCommon.Persistence.Dapper.Crud; using RCommon.Persistence.Crud; +using Microsoft.Extensions.DependencyInjection.Extensions; namespace RCommon { @@ -37,13 +38,15 @@ public IDapperBuilder AddDbConnection(string dataStoreName, Actio Guard.Against(dataStoreName.IsNullOrEmpty(), "You must set a name for the Data Store"); Guard.Against(options == null, "You must configure the options for the RDbConnection for it to be useful"); - if (!StaticDataStore.DataStores.TryAdd(dataStoreName, typeof(TDbConnection))) - { - throw new UnsupportedDataStoreException($"The StaticDataStore refused to add the new DataStore name: {dataStoreName} of type: {typeof(TDbConnection).AssemblyQualifiedName}"); - } - var dbContext = typeof(TDbConnection).AssemblyQualifiedName; - this._services.AddTransient(Type.GetType(dbContext), Type.GetType(dbContext)); + //this._services.AddTransient(Type.GetType(dbContext), Type.GetType(dbContext)); + + this._services.TryAddTransient(); + this._services.TryAddTransient(Type.GetType(dbContext)); + this._services.Configure(options => options.Register(dataStoreName)); + + //var dbContext = typeof(TDbConnection).AssemblyQualifiedName; + //this._services.AddTransient(Type.GetType(dbContext), Type.GetType(dbContext)); this._services.Configure(options); return this; diff --git a/Src/RCommon.EfCore/Crud/EFCoreRepository.cs b/Src/RCommon.EfCore/Crud/EFCoreRepository.cs index 52eab6f6..2b5e844a 100644 --- a/Src/RCommon.EfCore/Crud/EFCoreRepository.cs +++ b/Src/RCommon.EfCore/Crud/EFCoreRepository.cs @@ -35,6 +35,7 @@ public class EFCoreRepository : GraphRepositoryBase private IQueryable _repositoryQuery; private bool _tracking; private IIncludableQueryable _includableQueryable; + private readonly IDataStoreFactory _dataStoreFactory; @@ -44,13 +45,29 @@ public class EFCoreRepository : GraphRepositoryBase /// The is injected with scoped lifetime so it will always return the same instance of the /// througout the HTTP request or the scope of the thread. /// Logger used throughout the application. - public EFCoreRepository(IDataStoreRegistry dataStoreRegistry, IDataStoreEnlistmentProvider dataStoreEnlistmentProvider, - ILoggerFactory logger, IUnitOfWorkManager unitOfWorkManager, IEntityEventTracker eventTracker, + public EFCoreRepository(IDataStoreFactory dataStoreFactory, + ILoggerFactory logger, IEntityEventTracker eventTracker, IOptions defaultDataStoreOptions) - : base(dataStoreRegistry, dataStoreEnlistmentProvider, unitOfWorkManager, eventTracker, defaultDataStoreOptions) + : base(dataStoreFactory, eventTracker, defaultDataStoreOptions) { + if (logger is null) + { + throw new ArgumentNullException(nameof(logger)); + } + + if (eventTracker is null) + { + throw new ArgumentNullException(nameof(eventTracker)); + } + + if (defaultDataStoreOptions is null) + { + throw new ArgumentNullException(nameof(defaultDataStoreOptions)); + } + Logger = logger.CreateLogger(GetType().Name); _tracking = true; + _dataStoreFactory = dataStoreFactory ?? throw new ArgumentNullException(nameof(dataStoreFactory)); } protected DbSet ObjectSet @@ -231,7 +248,7 @@ protected internal RCommonDbContext ObjectContext { get { - return DataStoreRegistry.GetDataStore(DataStoreName); + return this._dataStoreFactory.Resolve(this.DataStoreName); } } @@ -240,15 +257,12 @@ private async Task SaveAsync(CancellationToken token = default) int affected = 0; try { - if (UnitOfWorkManager.CurrentUnitOfWork == null) - { - affected = await ObjectContext.SaveChangesAsync(true, token); // This will dispatch the local events - } + affected = await ObjectContext.SaveChangesAsync(true, token); } - catch (ApplicationException exception) + catch (ApplicationException ex) { - Logger.LogError(exception, "Error in {0}.SaveAsync while executing on the Context.", GetType().FullName); - throw; + var persistEx = new PersistenceException($"Error in {this.GetGenericTypeName()}.SaveAsync while executing on the Context.", ex); + throw persistEx; } return affected; diff --git a/Src/RCommon.EfCore/EFCorePerisistenceBuilder.cs b/Src/RCommon.EfCore/EFCorePerisistenceBuilder.cs index f6cc803d..30d147cc 100644 --- a/Src/RCommon.EfCore/EFCorePerisistenceBuilder.cs +++ b/Src/RCommon.EfCore/EFCorePerisistenceBuilder.cs @@ -2,8 +2,11 @@ using System.Collections; using System.Collections.Generic; using System.ComponentModel; +using System.Threading.Tasks; +using System.Xml.Linq; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using RCommon.Persistence; using RCommon.Persistence.Crud; using RCommon.Persistence.EFCore; @@ -34,11 +37,10 @@ public IEFCorePersistenceBuilder AddDbContext(string dataStoreName, where TDbContext : RCommonDbContext { Guard.Against(dataStoreName.IsNullOrEmpty(), "You must set a name for the Data Store"); - - if (!StaticDataStore.DataStores.TryAdd(dataStoreName, typeof(TDbContext))) - { - throw new UnsupportedDataStoreException($"The StaticDataStore refused to add the new DataStore name: {dataStoreName} of type: {typeof(TDbContext).AssemblyQualifiedName}"); - } + + this._services.TryAddTransient(); + //this._services.TryAddTransient(); + this._services.Configure(options => options.Register(dataStoreName)); this._services.AddDbContext(options, ServiceLifetime.Scoped); return this; diff --git a/Src/RCommon.EfCore/RCommonDbContext.cs b/Src/RCommon.EfCore/RCommonDbContext.cs index 5e820be3..f2182897 100644 --- a/Src/RCommon.EfCore/RCommonDbContext.cs +++ b/Src/RCommon.EfCore/RCommonDbContext.cs @@ -15,10 +15,8 @@ namespace RCommon.Persistence.EFCore { public abstract class RCommonDbContext : DbContext, IDataStore { - private readonly IEntityEventTracker _entityEventTracker; - - public RCommonDbContext(DbContextOptions options, IEntityEventTracker entityEventTracker) + public RCommonDbContext(DbContextOptions options) : base(options) { if (options is null) @@ -26,35 +24,13 @@ public RCommonDbContext(DbContextOptions options, IEntityEventTracker entityEven throw new ArgumentNullException(nameof(options)); } - this._entityEventTracker = entityEventTracker ?? throw new ArgumentNullException(nameof(entityEventTracker)); } - public RCommonDbContext(DbContextOptions options) - : base(options) - { - if (options is null) - { - throw new ArgumentNullException(nameof(options)); - } - } - public DbConnection GetDbConnection() { return base.Database.GetDbConnection(); } - - public virtual async Task PersistChangesAsync() - { - await this.SaveChangesAsync(true); - } - - - public override async Task SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default) - { - await this._entityEventTracker.EmitTransactionalEventsAsync(); - return await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); - } } } diff --git a/Src/RCommon.Linq2Db/Crud/Linq2DbRepository.cs b/Src/RCommon.Linq2Db/Crud/Linq2DbRepository.cs index 741514c2..b6b05d60 100644 --- a/Src/RCommon.Linq2Db/Crud/Linq2DbRepository.cs +++ b/Src/RCommon.Linq2Db/Crud/Linq2DbRepository.cs @@ -24,15 +24,32 @@ public class Linq2DbRepository : LinqRepositoryBase { private IQueryable _repositoryQuery; private ILoadWithQueryable _includableQueryable; + private readonly IDataStoreFactory _dataStoreFactory; - public Linq2DbRepository(IDataStoreRegistry dataStoreRegistry, IDataStoreEnlistmentProvider dataStoreEnlistmentProvider, - ILoggerFactory logger, IUnitOfWorkManager unitOfWorkManager, IEntityEventTracker eventTracker, + public Linq2DbRepository(IDataStoreFactory dataStoreFactory, + ILoggerFactory logger, IEntityEventTracker eventTracker, IOptions defaultDataStoreOptions) - : base(dataStoreRegistry, dataStoreEnlistmentProvider, unitOfWorkManager, eventTracker, defaultDataStoreOptions) + : base(dataStoreFactory, eventTracker, defaultDataStoreOptions) { + if (logger is null) + { + throw new ArgumentNullException(nameof(logger)); + } + + if (eventTracker is null) + { + throw new ArgumentNullException(nameof(eventTracker)); + } + + if (defaultDataStoreOptions is null) + { + throw new ArgumentNullException(nameof(defaultDataStoreOptions)); + } + Logger = logger.CreateLogger(GetType().Name); _repositoryQuery = null; _includableQueryable = null; + _dataStoreFactory = dataStoreFactory ?? throw new ArgumentNullException(nameof(dataStoreFactory)); } @@ -40,7 +57,7 @@ protected internal RCommonDataConnection DataConnection { get { - return DataStoreRegistry.GetDataStore(DataStoreName); + return this._dataStoreFactory.Resolve(this.DataStoreName); } } @@ -214,22 +231,5 @@ public async override Task UpdateAsync(TEntity entity, CancellationToken token = entity.AddLocalEvent(new EntityUpdatedEvent(entity)); EventTracker.AddEntity(entity); } - - protected async Task DispatchEvents() - { - try - { - if (!UnitOfWorkManager.IsUnitOfWorkActive) - { - Guard.Against(DataConnection == null, "DataConnection is null"); - await DataConnection.PersistChangesAsync(); // This dispatches the events - } - } - catch (ApplicationException exception) - { - Logger.LogError(exception, "Error in {0}.DispatchEvents while executing on the Context.", GetType().FullName); - throw; - } - } } } diff --git a/Src/RCommon.Linq2Db/Linq2DbPersistenceBuilder.cs b/Src/RCommon.Linq2Db/Linq2DbPersistenceBuilder.cs index e46e90af..c36d4d2f 100644 --- a/Src/RCommon.Linq2Db/Linq2DbPersistenceBuilder.cs +++ b/Src/RCommon.Linq2Db/Linq2DbPersistenceBuilder.cs @@ -12,6 +12,7 @@ using System.Threading.Tasks; using RCommon.Persistence.Linq2Db.Crud; using RCommon.Persistence.Crud; +using Microsoft.Extensions.DependencyInjection.Extensions; namespace RCommon.Persistence.Linq2Db { @@ -37,10 +38,9 @@ public ILinq2DbPersistenceBuilder AddDataConnection(string data Guard.Against(dataStoreName.IsNullOrEmpty(), "You must set a name for the Data Store"); Guard.Against(options == null, "You must set options to a value in order for them to be useful"); - if (!StaticDataStore.DataStores.TryAdd(dataStoreName, typeof(TDataConnection))) - { - throw new UnsupportedDataStoreException($"The StaticDataStore refused to add the new DataStore name: {dataStoreName} of type: {typeof(TDataConnection).AssemblyQualifiedName}"); - } + this._services.TryAddTransient(); + this._services.TryAddTransient(); + this._services.Configure(options => options.Register(dataStoreName)); _services.AddLinqToDBContext(options); return this; diff --git a/Src/RCommon.Linq2Db/RCommonDataConnection.cs b/Src/RCommon.Linq2Db/RCommonDataConnection.cs index ba82b37c..f180b902 100644 --- a/Src/RCommon.Linq2Db/RCommonDataConnection.cs +++ b/Src/RCommon.Linq2Db/RCommonDataConnection.cs @@ -21,8 +21,6 @@ public class RCommonDataConnection : DataConnection, IDataStore public RCommonDataConnection(IEntityEventTracker eventTracker, DataOptions linq2DbOptions) :base(linq2DbOptions) { - var options = linq2DbOptions ?? throw new ArgumentNullException(nameof(linq2DbOptions)); - _eventTracker = eventTracker ?? throw new ArgumentNullException(nameof(eventTracker)); } @@ -32,10 +30,5 @@ public DbConnection GetDbConnection() { return this.Connection; } - - public async Task PersistChangesAsync() - { - await this._eventTracker.EmitTransactionalEventsAsync(); - } } } diff --git a/Src/RCommon.Mediatr/Behaviors/UnitOfWorkBehavior.cs b/Src/RCommon.Mediatr/Behaviors/UnitOfWorkBehavior.cs index 5722e172..2f8b8ef9 100644 --- a/Src/RCommon.Mediatr/Behaviors/UnitOfWorkBehavior.cs +++ b/Src/RCommon.Mediatr/Behaviors/UnitOfWorkBehavior.cs @@ -13,13 +13,11 @@ public class UnitOfWorkRequestBehavior : IPipelineBehavior< { private readonly ILogger> _logger; private readonly IUnitOfWorkFactory _unitOfWorkScopeFactory; - private readonly IUnitOfWorkManager _unitOfWorkManager; - public UnitOfWorkRequestBehavior(IUnitOfWorkFactory unitOfWorkScopeFactory, IUnitOfWorkManager unitOfWorkManager, + public UnitOfWorkRequestBehavior(IUnitOfWorkFactory unitOfWorkScopeFactory, ILogger> logger) { _unitOfWorkScopeFactory = unitOfWorkScopeFactory ?? throw new ArgumentException(nameof(IUnitOfWorkFactory)); - _unitOfWorkManager = unitOfWorkManager ?? throw new ArgumentException(nameof(IUnitOfWorkManager)); _logger = logger ?? throw new ArgumentException(nameof(ILogger)); } @@ -30,17 +28,17 @@ public async Task Handle(TRequest request, RequestHandlerDelegate : IPipel { private readonly ILogger> _logger; private readonly IUnitOfWorkFactory _unitOfWorkScopeFactory; - private readonly IUnitOfWorkManager _unitOfWorkManager; - public UnitOfWorkRequestWithResponseBehavior(IUnitOfWorkFactory unitOfWorkScopeFactory, IUnitOfWorkManager unitOfWorkManager, + public UnitOfWorkRequestWithResponseBehavior(IUnitOfWorkFactory unitOfWorkScopeFactory, ILogger> logger) { _unitOfWorkScopeFactory = unitOfWorkScopeFactory ?? throw new ArgumentException(nameof(IUnitOfWorkFactory)); - _unitOfWorkManager = unitOfWorkManager ?? throw new ArgumentException(nameof(IUnitOfWorkManager)); _logger = logger ?? throw new ArgumentException(nameof(ILogger)); } @@ -77,17 +73,17 @@ public async Task Handle(TRequest request, RequestHandlerDelegate _logger; - private readonly IServiceProvider _serviceProvider; - - public CachedDataStoreRegistry(IMemoryCache memoryCache, ILogger logger, IServiceProvider serviceProvider) - { - _memoryCache = memoryCache ?? throw new ArgumentNullException(nameof(memoryCache)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); - } - - public void RegisterDataStore(TDataStore dataStore, string dataStoreName) - where TDataStore : IDataStore - { - var newTypeName = dataStore.GetType().AssemblyQualifiedName; - this._memoryCache.Set(dataStoreName, newTypeName); - this._logger.LogInformation("Registered new Data Store: {0}", newTypeName); - } - - public TDataStore GetDataStore(string dataStoreName) - where TDataStore : IDataStore - { - string dataStoreTypeName; - if (this._memoryCache.TryGetValue(dataStoreName, out dataStoreTypeName)) - { - - TDataStore dataStore = (TDataStore) this._serviceProvider.GetService(Type.GetType(dataStoreTypeName)); - return dataStore; - } - else - { - throw new UnsupportedDataStoreException($"A Data Store with the name of: {dataStoreName} and type of: {dataStoreTypeName} was not registered or found"); - } - } - - public IDataStore GetDataStore(string dataStoreName) - { - string dataStoreTypeName; - if (this._memoryCache.TryGetValue(dataStoreName, out dataStoreTypeName)) - { - - var dataStore = (IDataStore)this._serviceProvider.GetService(Type.GetType(dataStoreTypeName)); - return dataStore; - } - else - { - throw new UnsupportedDataStoreException($"A Data Store with the name of: {dataStoreName} and type of: {dataStoreTypeName} was not registered or found"); - } - } - - public void RemoveRegisteredDataStore(string dataStoreName) - { - this._memoryCache.Remove(dataStoreName); - } - } -} diff --git a/Src/RCommon.Persistence/Crud/GraphRepositoryBase.cs b/Src/RCommon.Persistence/Crud/GraphRepositoryBase.cs index 7f0285cb..71616d0d 100644 --- a/Src/RCommon.Persistence/Crud/GraphRepositoryBase.cs +++ b/Src/RCommon.Persistence/Crud/GraphRepositoryBase.cs @@ -22,9 +22,9 @@ public abstract class GraphRepositoryBase : LinqRepositoryBase where TEntity : class, IBusinessEntity { - public GraphRepositoryBase(IDataStoreRegistry dataStoreRegistry, IDataStoreEnlistmentProvider dataStoreEnlistmentProvider, - IUnitOfWorkManager unitOfWorkManager, IEntityEventTracker eventTracker, IOptions defaultDataStoreOptions) - :base(dataStoreRegistry, dataStoreEnlistmentProvider, unitOfWorkManager, eventTracker, defaultDataStoreOptions) + public GraphRepositoryBase(IDataStoreFactory dataStoreFactory, + IEntityEventTracker eventTracker, IOptions defaultDataStoreOptions) + :base(dataStoreFactory, eventTracker, defaultDataStoreOptions) { } diff --git a/Src/RCommon.Persistence/Crud/LinqRepositoryBase.cs b/Src/RCommon.Persistence/Crud/LinqRepositoryBase.cs index 0c552549..a5ca8eea 100644 --- a/Src/RCommon.Persistence/Crud/LinqRepositoryBase.cs +++ b/Src/RCommon.Persistence/Crud/LinqRepositoryBase.cs @@ -20,14 +20,16 @@ public abstract class LinqRepositoryBase : DisposableResource, ILinqRep where TEntity : IBusinessEntity { private string _dataStoreName; - private readonly IDataStoreEnlistmentProvider _dataStoreEnlistmentProvider; + private readonly IDataStoreFactory _dataStoreFactory; - public LinqRepositoryBase(IDataStoreRegistry dataStoreRegistry, IDataStoreEnlistmentProvider dataStoreEnlistmentProvider, - IUnitOfWorkManager unitOfWorkManager, IEntityEventTracker eventTracker, IOptions defaultDataStoreOptions) + public LinqRepositoryBase(IDataStoreFactory dataStoreFactory, + IEntityEventTracker eventTracker, IOptions defaultDataStoreOptions) { - DataStoreRegistry = dataStoreRegistry ?? throw new ArgumentNullException(nameof(dataStoreRegistry)); - _dataStoreEnlistmentProvider = dataStoreEnlistmentProvider ?? throw new ArgumentNullException(nameof(dataStoreEnlistmentProvider)); - UnitOfWorkManager = unitOfWorkManager ?? throw new ArgumentNullException(nameof(unitOfWorkManager)); + if (defaultDataStoreOptions is null) + { + throw new ArgumentNullException(nameof(defaultDataStoreOptions)); + } + _dataStoreFactory = dataStoreFactory ?? throw new ArgumentNullException(nameof(dataStoreFactory)); EventTracker = eventTracker ?? throw new ArgumentNullException(nameof(eventTracker)); if (defaultDataStoreOptions != null && defaultDataStoreOptions.Value != null @@ -142,10 +144,7 @@ public abstract Task> FindAsync(Expression Include(Expression> path); public abstract IEagerLoadableQueryable ThenInclude(Expression> path); - - public IDataStoreRegistry DataStoreRegistry { get; } public ILogger Logger { get; set; } - public IUnitOfWorkManager UnitOfWorkManager { get; } public IEntityEventTracker EventTracker { get; } public string DataStoreName { @@ -153,13 +152,6 @@ public string DataStoreName set { _dataStoreName = value; - var dataStore = this.DataStoreRegistry.GetDataStore(_dataStoreName); - - // Enlist Data Stores that are participating in transactions - if (this.UnitOfWorkManager.IsUnitOfWorkActive) - { - this._dataStoreEnlistmentProvider.EnlistDataStore(this.UnitOfWorkManager.CurrentUnitOfWorkTransactionId, dataStore); - } } } } diff --git a/Src/RCommon.Persistence/Crud/SqlRepositoryBase.cs b/Src/RCommon.Persistence/Crud/SqlRepositoryBase.cs index dafd7299..d5b4007d 100644 --- a/Src/RCommon.Persistence/Crud/SqlRepositoryBase.cs +++ b/Src/RCommon.Persistence/Crud/SqlRepositoryBase.cs @@ -21,15 +21,23 @@ public abstract class SqlRepositoryBase : DisposableResource, ISqlMappe where TEntity : class, IBusinessEntity { private string _dataStoreName; - private readonly IDataStoreEnlistmentProvider _dataStoreEnlistmentProvider; + private readonly IDataStoreFactory _dataStoreFactory; - public SqlRepositoryBase(IDataStoreRegistry dataStoreRegistry, IDataStoreEnlistmentProvider dataStoreEnlistmentProvider, - ILoggerFactory logger, IUnitOfWorkManager unitOfWorkManager, IEntityEventTracker eventTracker, + public SqlRepositoryBase(IDataStoreFactory dataStoreFactory, + ILoggerFactory logger, IEntityEventTracker eventTracker, IOptions defaultDataStoreOptions) { - DataStoreRegistry = dataStoreRegistry ?? throw new ArgumentNullException(nameof(dataStoreRegistry)); - _dataStoreEnlistmentProvider = dataStoreEnlistmentProvider ?? throw new ArgumentNullException(nameof(dataStoreEnlistmentProvider)); - UnitOfWorkManager = unitOfWorkManager ?? throw new ArgumentNullException(nameof(unitOfWorkManager)); + if (logger is null) + { + throw new ArgumentNullException(nameof(logger)); + } + + if (defaultDataStoreOptions is null) + { + throw new ArgumentNullException(nameof(defaultDataStoreOptions)); + } + + _dataStoreFactory = dataStoreFactory ?? throw new ArgumentNullException(nameof(dataStoreFactory)); EventTracker = eventTracker ?? throw new ArgumentNullException(nameof(eventTracker)); if (defaultDataStoreOptions != null && defaultDataStoreOptions.Value != null @@ -60,7 +68,7 @@ protected internal RDbConnection DataStore { get { - return this.DataStoreRegistry.GetDataStore(this.DataStoreName); + return this._dataStoreFactory.Resolve(this.DataStoreName); } } @@ -70,19 +78,10 @@ public string DataStoreName set { _dataStoreName = value; - var dataStore = this.DataStoreRegistry.GetDataStore(_dataStoreName); - - // Enlist Data Stores that are participating in transactions - if (this.UnitOfWorkManager.IsUnitOfWorkActive) - { - this._dataStoreEnlistmentProvider.EnlistDataStore(this.UnitOfWorkManager.CurrentUnitOfWorkTransactionId, dataStore); - } } } - public IDataStoreRegistry DataStoreRegistry { get; } public ILogger Logger { get; set; } - public IUnitOfWorkManager UnitOfWorkManager { get; } public IEntityEventTracker EventTracker { get; } } diff --git a/Src/RCommon.Persistence/DataStoreFactory.cs b/Src/RCommon.Persistence/DataStoreFactory.cs new file mode 100644 index 00000000..d20f0029 --- /dev/null +++ b/Src/RCommon.Persistence/DataStoreFactory.cs @@ -0,0 +1,44 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RCommon.Persistence +{ + public class DataStoreFactory : IDataStoreFactory + { + private readonly IServiceProvider _provider; + private readonly IDictionary _types; + + public DataStoreFactory(IServiceProvider provider, IOptions options) + { + _provider = provider; + _types = options.Value.Types; + } + + public IDataStore Resolve(string name) + { + if (_types.TryGetValue(name, out var type)) + { + return (IDataStore)_provider.GetRequiredService(type); + } + + throw new ArgumentOutOfRangeException(nameof(name)); + } + + public TDataStore Resolve(string name) + where TDataStore : IDataStore + { + if (_types.TryGetValue(name, out var type)) + { + return (TDataStore)_provider.GetRequiredService(type); + } + + throw new ArgumentOutOfRangeException(nameof(name)); + } + } +} diff --git a/Src/RCommon.Persistence/DataStoreFactoryOptions.cs b/Src/RCommon.Persistence/DataStoreFactoryOptions.cs new file mode 100644 index 00000000..0fd73c6e --- /dev/null +++ b/Src/RCommon.Persistence/DataStoreFactoryOptions.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RCommon.Persistence +{ + public class DataStoreFactoryOptions + { + public IDictionary Types { get; } = new Dictionary(); + + public void Register(string name) where T : IDataStore + { + Types.Add(name, typeof(T)); + } + } +} diff --git a/Src/RCommon.Persistence/IDataStore.cs b/Src/RCommon.Persistence/IDataStore.cs index a0b2c85f..17d945be 100644 --- a/Src/RCommon.Persistence/IDataStore.cs +++ b/Src/RCommon.Persistence/IDataStore.cs @@ -9,8 +9,6 @@ namespace RCommon.Persistence { public interface IDataStore : IAsyncDisposable { - - Task PersistChangesAsync(); DbConnection GetDbConnection(); } diff --git a/Src/RCommon.Persistence/IDataStoreEnlistmentProvider.cs b/Src/RCommon.Persistence/IDataStoreEnlistmentProvider.cs deleted file mode 100644 index e4bef45d..00000000 --- a/Src/RCommon.Persistence/IDataStoreEnlistmentProvider.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; - -namespace RCommon.Persistence -{ - public interface IDataStoreEnlistmentProvider - { - ConcurrentDictionary DataStores { get; } - - bool EnlistDataStore(Guid transactionId, IDataStore dataStore); - IList GetEnlistedDataStores(Guid transactionId); - - bool RemoveEnlistedDataStores(Guid transactionId); - } -} diff --git a/Src/RCommon.Persistence/IDataStoreFactory.cs b/Src/RCommon.Persistence/IDataStoreFactory.cs new file mode 100644 index 00000000..1dea9318 --- /dev/null +++ b/Src/RCommon.Persistence/IDataStoreFactory.cs @@ -0,0 +1,9 @@ +namespace RCommon.Persistence +{ + public interface IDataStoreFactory + { + IDataStore Resolve(string name); + TDataStore Resolve(string name) + where TDataStore : IDataStore; + } +} diff --git a/Src/RCommon.Persistence/IDataStoreRegistry.cs b/Src/RCommon.Persistence/IDataStoreRegistry.cs deleted file mode 100644 index 591444de..00000000 --- a/Src/RCommon.Persistence/IDataStoreRegistry.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace RCommon.Persistence -{ - public interface IDataStoreRegistry - { - TDataStore GetDataStore(string dataStoreName) where TDataStore : IDataStore; - IDataStore GetDataStore(string dataStoreName); - void RegisterDataStore(TDataStore dataStore, string dataStoreName) where TDataStore : IDataStore; - void RemoveRegisteredDataStore(string dataStoreName); - } -} diff --git a/Src/RCommon.Persistence/PersistenceBuilderExtensions.cs b/Src/RCommon.Persistence/PersistenceBuilderExtensions.cs index c561cfc9..0ec6535d 100644 --- a/Src/RCommon.Persistence/PersistenceBuilderExtensions.cs +++ b/Src/RCommon.Persistence/PersistenceBuilderExtensions.cs @@ -47,8 +47,13 @@ public static IRCommonBuilder WithPersistence(this I where TUnitOfWork : IUnitOfWorkBuilder { // Data Store Management - builder.Services.AddScoped(); - builder.Services.AddScoped(); + //var dataStore = new ScopedDataStore(); + //var dataStoreActions = new Action(x => {}); ; + //dataStoreActions(dataStore); + //builder.Services.Configure(dataStoreActions); + //builder.Services.AddScoped(); + //builder.Services.AddDistributedMemoryCache(); + //builder.Services.AddScoped(); // Object Access and Unit of Work Configurations // Wire up the "out of the box" events/event handlers used in persistence. These are not transactional diff --git a/Src/RCommon.Persistence/PersistenceException.cs b/Src/RCommon.Persistence/PersistenceException.cs new file mode 100644 index 00000000..9b2ae7b8 --- /dev/null +++ b/Src/RCommon.Persistence/PersistenceException.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RCommon.Persistence +{ + public class PersistenceException : GeneralException + { + public PersistenceException(string message, Exception exception) : base(message, exception) + { + + } + } +} diff --git a/Src/RCommon.Persistence/ScopedDataStore.cs b/Src/RCommon.Persistence/ScopedDataStore.cs deleted file mode 100644 index 78c597b4..00000000 --- a/Src/RCommon.Persistence/ScopedDataStore.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace RCommon.Persistence -{ - public class ScopedDataStore : IScopedDataStore - { - - public ScopedDataStore() - { - DataStores = new ConcurrentDictionary(); - } - - public ConcurrentDictionary DataStores { get; set; } - } -} diff --git a/Src/RCommon.Persistence/ScopedDataStoreEnlistmentProvider.cs b/Src/RCommon.Persistence/ScopedDataStoreEnlistmentProvider.cs deleted file mode 100644 index 22fa6a0f..00000000 --- a/Src/RCommon.Persistence/ScopedDataStoreEnlistmentProvider.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace RCommon.Persistence -{ - public class ScopedDataStoreEnlistmentProvider : IDataStoreEnlistmentProvider - { - public ScopedDataStoreEnlistmentProvider() - { - DataStores = new ConcurrentDictionary(); - } - - public bool EnlistDataStore(Guid transactionId, IDataStore dataStore) - { - var dataStoreValue = DataStores.GetOrAdd(transactionId, dataStore); - - if (dataStoreValue == null) - { - return false; - } - return true; - - } - - public IList GetEnlistedDataStores(Guid transactionId) - { - var dataStores = DataStores.Where(x => x.Key == transactionId) - .Select(x => x.Value).ToList(); - return dataStores; - } - - public bool RemoveEnlistedDataStores(Guid transactionId) - { - var dataStores = DataStores.Where(x => x.Key == transactionId); - foreach (var item in dataStores) - { - if (!DataStores.TryRemove(item)) - { - return false; - } - - } - return true; - } - - public ConcurrentDictionary DataStores { get; } - } -} diff --git a/Src/RCommon.Persistence/ScopedDataStoreRegistry.cs b/Src/RCommon.Persistence/ScopedDataStoreRegistry.cs deleted file mode 100644 index f0e96aec..00000000 --- a/Src/RCommon.Persistence/ScopedDataStoreRegistry.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace RCommon.Persistence -{ - public class ScopedDataStoreRegistry : IDataStoreRegistry - { - private readonly IServiceProvider _serviceProvider; - private readonly IScopedDataStore _scopedDataStore; - - public ScopedDataStoreRegistry(IServiceProvider serviceProvider, IScopedDataStore scopedDataStore) - { - _serviceProvider = serviceProvider; - _scopedDataStore = scopedDataStore; - } - - public TDataStore GetDataStore(string dataStoreName) where TDataStore : IDataStore - { - var type = _scopedDataStore.DataStores.Where(x => x.Key == dataStoreName).FirstOrDefault().Value; - Guard.Against(type == null, - this.GetGenericTypeName() + " could not find a DataStore with the key of: " + dataStoreName); - return (TDataStore)this._serviceProvider.GetService(type); - } - - public IDataStore GetDataStore(string dataStoreName) - { - var type = _scopedDataStore.DataStores.Where(x => x.Key == dataStoreName).FirstOrDefault().Value; - Guard.Against(type == null, - this.GetGenericTypeName() + " could not find a DataStore with the key of: " + dataStoreName); - return (IDataStore)this._serviceProvider.GetService(type); - } - - public void RegisterDataStore(TDataStore dataStore, string dataStoreName) where TDataStore : IDataStore - { - if (!_scopedDataStore.DataStores.TryAdd(dataStoreName, typeof(TDataStore))) - { - throw new UnsupportedDataStoreException($"The ScopedDataStore refused to add the new DataStore name: {dataStoreName} of type: {dataStore.GetType().AssemblyQualifiedName}"); - } - } - - public void RemoveRegisteredDataStore(string dataStoreName) - { - if (!_scopedDataStore.DataStores.TryRemove(dataStoreName, out _)) - { - throw new UnsupportedDataStoreException($"The ScopedDataStore refused to remove the DataStore name: {dataStoreName}"); - } - } - } -} diff --git a/Src/RCommon.Persistence/Sql/RDbConnection.cs b/Src/RCommon.Persistence/Sql/RDbConnection.cs index 12ee137a..a1667765 100644 --- a/Src/RCommon.Persistence/Sql/RDbConnection.cs +++ b/Src/RCommon.Persistence/Sql/RDbConnection.cs @@ -16,10 +16,9 @@ public class RDbConnection : DisposableResource, IRDbConnection private readonly IOptions _options; private readonly IEntityEventTracker _entityEventTracker; - public RDbConnection(IOptions options, IEntityEventTracker entityEventTracker) + public RDbConnection(IOptions options) { _options = options ?? throw new ArgumentNullException(nameof(options)); - this._entityEventTracker = entityEventTracker ?? throw new ArgumentNullException(nameof(entityEventTracker)); } public DbConnection GetDbConnection() @@ -35,10 +34,5 @@ public DbConnection GetDbConnection() return connection; } - public async Task PersistChangesAsync() - { - await this._entityEventTracker.EmitTransactionalEventsAsync(); - } - } } diff --git a/Src/RCommon.Persistence/StaticDataStore.cs b/Src/RCommon.Persistence/StaticDataStore.cs deleted file mode 100644 index ec159453..00000000 --- a/Src/RCommon.Persistence/StaticDataStore.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace RCommon.Persistence -{ - public sealed class StaticDataStore - { - - private static readonly Lazy lazy = - new Lazy(() => new StaticDataStore()); - - public static StaticDataStore Instance { get { return lazy.Value; } } - - private StaticDataStore() - { - } - - public static ConcurrentDictionary DataStores { get; set; } - } -} diff --git a/Src/RCommon.Persistence/StaticDataStoreRegistry.cs b/Src/RCommon.Persistence/StaticDataStoreRegistry.cs deleted file mode 100644 index 996fe302..00000000 --- a/Src/RCommon.Persistence/StaticDataStoreRegistry.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; - -namespace RCommon.Persistence -{ - public class StaticDataStoreRegistry : IDataStoreRegistry - { - private readonly IServiceProvider _serviceProvider; - - public StaticDataStoreRegistry(IServiceProvider serviceProvider) - { - _serviceProvider = serviceProvider; - } - - - public TDataStore GetDataStore(string dataStoreName) - where TDataStore : IDataStore - { - var type = StaticDataStore.DataStores.Where(x => x.Key == dataStoreName).FirstOrDefault().Value; - Guard.Against(type == null, - this.GetGenericTypeName() + " could not find a DataStore with the key of: " + dataStoreName); - return (TDataStore)this._serviceProvider.GetService(type); - } - - public IDataStore GetDataStore(string dataStoreName) - { - var type = StaticDataStore.DataStores.Where(x => x.Key == dataStoreName).FirstOrDefault().Value; - Guard.Against(type == null, - this.GetGenericTypeName() + " could not find a DataStore with the key of: " + dataStoreName); - return (IDataStore) this._serviceProvider.GetService(type); - } - - public void RegisterDataStore(TDataStore dataStore, string dataStoreName) - where TDataStore : IDataStore - { - if (!StaticDataStore.DataStores.TryAdd(dataStoreName, typeof(TDataStore))) - { - throw new UnsupportedDataStoreException($"The StaticDataStore refused to add the new DataStore name: {dataStoreName} of type: {dataStore.GetType().AssemblyQualifiedName}"); - } - } - - public void RemoveRegisteredDataStore(string dataStoreName) - { - if (!StaticDataStore.DataStores.TryRemove(dataStoreName, out _)) - { - throw new UnsupportedDataStoreException($"The StaticDataStore refused to remove the DataStore name: {dataStoreName}"); - } - } - } -} diff --git a/Src/RCommon.Persistence/Transactions/DefaultUnitOfWorkBuilder.cs b/Src/RCommon.Persistence/Transactions/DefaultUnitOfWorkBuilder.cs index 0b7b61df..04ca917c 100644 --- a/Src/RCommon.Persistence/Transactions/DefaultUnitOfWorkBuilder.cs +++ b/Src/RCommon.Persistence/Transactions/DefaultUnitOfWorkBuilder.cs @@ -35,11 +35,6 @@ public class DefaultUnitOfWorkBuilder : IUnitOfWorkBuilder public DefaultUnitOfWorkBuilder(IServiceCollection services) { - // Data Store Management - services.AddScoped(); - - // Transaction Management - services.AddScoped(); // Factory for Unit Of Work Scope services.AddTransient(); diff --git a/Src/RCommon.Persistence/Transactions/IUnitOfWork.cs b/Src/RCommon.Persistence/Transactions/IUnitOfWork.cs index 2fdc345f..d78b940a 100644 --- a/Src/RCommon.Persistence/Transactions/IUnitOfWork.cs +++ b/Src/RCommon.Persistence/Transactions/IUnitOfWork.cs @@ -4,7 +4,7 @@ namespace RCommon.Persistence.Transactions { - public interface IUnitOfWork : IAsyncDisposable + public interface IUnitOfWork : IDisposable { bool AutoComplete { get; } IsolationLevel IsolationLevel { get; set; } @@ -12,6 +12,6 @@ public interface IUnitOfWork : IAsyncDisposable Guid TransactionId { get; } TransactionMode TransactionMode { get; set; } - Task CommitAsync(); + void Commit(); } } diff --git a/Src/RCommon.Persistence/Transactions/IUnitOfWorkFactory.cs b/Src/RCommon.Persistence/Transactions/IUnitOfWorkFactory.cs index b9f14fa4..20a6a296 100644 --- a/Src/RCommon.Persistence/Transactions/IUnitOfWorkFactory.cs +++ b/Src/RCommon.Persistence/Transactions/IUnitOfWorkFactory.cs @@ -5,8 +5,8 @@ namespace RCommon.Persistence.Transactions { public interface IUnitOfWorkFactory { - Task CreateAsync(); - Task CreateAsync(TransactionMode transactionMode); - Task CreateAsync(TransactionMode transactionMode, IsolationLevel isolationLevel); + IUnitOfWork Create(); + IUnitOfWork Create(TransactionMode transactionMode); + IUnitOfWork Create(TransactionMode transactionMode, IsolationLevel isolationLevel); } -} \ No newline at end of file +} diff --git a/Src/RCommon.Persistence/Transactions/IUnitOfWorkManager.cs b/Src/RCommon.Persistence/Transactions/IUnitOfWorkManager.cs deleted file mode 100644 index 544ce490..00000000 --- a/Src/RCommon.Persistence/Transactions/IUnitOfWorkManager.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Threading.Tasks; - -namespace RCommon.Persistence.Transactions -{ - public interface IUnitOfWorkManager : IAsyncDisposable - { - [Obsolete("Please use UnitOfWorkManager.CurrentUnitOfWorkTransactionId. This will be removed in a future version.")] - IUnitOfWork CurrentUnitOfWork { get; } - - Guid CurrentUnitOfWorkTransactionId { get; } - - bool IsUnitOfWorkActive { get; } - - Task CommitUnitOfWorkAsync(IUnitOfWork unitOfWork); - Task CompleteUnitOfWorkAsync(IUnitOfWork unitOfWork); - bool EnlistUnitOfWork(IUnitOfWork unitOfWork); - Task RollbackUnitOfWorkAsync(IUnitOfWork unitOfWork); - } -} diff --git a/Src/RCommon.Persistence/Transactions/UnitOfWork.cs b/Src/RCommon.Persistence/Transactions/UnitOfWork.cs index 486760d0..d3497c9b 100644 --- a/Src/RCommon.Persistence/Transactions/UnitOfWork.cs +++ b/Src/RCommon.Persistence/Transactions/UnitOfWork.cs @@ -14,15 +14,13 @@ public class UnitOfWork : DisposableResource, IUnitOfWork { private readonly ILogger _logger; private readonly IGuidGenerator _guidGenerator; - private readonly IUnitOfWorkManager _unitOfWorkManager; private UnitOfWorkState _state; private TransactionScope _transactionScope; - public UnitOfWork(ILogger logger, IGuidGenerator guidGenerator, IOptions unitOfWorkSettings, IUnitOfWorkManager unitOfWorkManager) + public UnitOfWork(ILogger logger, IGuidGenerator guidGenerator, IOptions unitOfWorkSettings) { _logger = logger; _guidGenerator = guidGenerator; - _unitOfWorkManager = unitOfWorkManager; TransactionId = _guidGenerator.Create(); TransactionMode = TransactionMode.Default; @@ -30,14 +28,12 @@ public UnitOfWork(ILogger logger, IGuidGenerator guidGenerator, IOpt AutoComplete = unitOfWorkSettings.Value.AutoCompleteScope; _state = UnitOfWorkState.Created; _transactionScope = TransactionScopeHelper.CreateScope(_logger, this); - _unitOfWorkManager.EnlistUnitOfWork(this); } public UnitOfWork(ILogger logger, IGuidGenerator guidGenerator, TransactionMode transactionMode, IsolationLevel isolationLevel, - IEventBus eventBus, IUnitOfWorkManager unitOfWorkManager) + IEventBus eventBus) { _logger = logger; _guidGenerator = guidGenerator; - _unitOfWorkManager = unitOfWorkManager; TransactionId = _guidGenerator.Create(); TransactionMode = transactionMode; @@ -45,10 +41,9 @@ public UnitOfWork(ILogger logger, IGuidGenerator guidGenerator, Tran AutoComplete = false; _state = UnitOfWorkState.Created; _transactionScope = TransactionScopeHelper.CreateScope(_logger, this); - _unitOfWorkManager.EnlistUnitOfWork(this); } - public async Task CommitAsync() + public void Commit() { Guard.Against(_state == UnitOfWorkState.Disposed, "Cannot commit a disposed UnitOfWorkScope instance."); @@ -56,24 +51,21 @@ public async Task CommitAsync() "This unit of work scope has been marked completed. A child scope participating in the " + "transaction has rolledback and the transaction aborted. The parent scope cannot be commited."); _state = UnitOfWorkState.CommitAttempted; - await _unitOfWorkManager.CommitUnitOfWorkAsync(this); - await this.CompleteAsync(); + this.Complete(); } - private async Task RollbackAsync() + private void Rollback() { _state = UnitOfWorkState.RolledBack; - await _unitOfWorkManager.RollbackUnitOfWorkAsync(this); } - private async Task CompleteAsync() + private void Complete() { _transactionScope.Complete(); _state = UnitOfWorkState.Completed; - await _unitOfWorkManager.CompleteUnitOfWorkAsync(this); } - protected override async Task DisposeAsync(bool disposing) + protected override void Dispose(bool disposing) { if (_state == UnitOfWorkState.Disposed) { @@ -94,13 +86,13 @@ protected override async Task DisposeAsync(bool disposing) { //Scope did not try to commit before, and auto complete is switched on. Trying to commit. //If an exception occurs here, the finally block will clean things up for us. - await this.CommitAsync(); + this.Commit(); } else { //Scope either tried a commit before or auto complete is turned off. Trying to rollback. //If an exception occurs here, the finally block will clean things up for us. - await this.RollbackAsync(); + this.Rollback(); } } finally @@ -108,7 +100,7 @@ protected override async Task DisposeAsync(bool disposing) _transactionScope.Dispose(); _state = UnitOfWorkState.Disposed; _logger.LogDebug("UnitOfWork {0} Disposed.", TransactionId); - await this.DisposeAsync(); + this.Dispose(); } } } diff --git a/Src/RCommon.Persistence/Transactions/UnitOfWorkCommittedEvent.cs b/Src/RCommon.Persistence/Transactions/UnitOfWorkCommittedEvent.cs deleted file mode 100644 index d0176736..00000000 --- a/Src/RCommon.Persistence/Transactions/UnitOfWorkCommittedEvent.cs +++ /dev/null @@ -1,19 +0,0 @@ -using RCommon.EventHandling; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace RCommon.Persistence.Transactions -{ - public record UnitOfWorkCommittedEvent : ISyncEvent - { - public UnitOfWorkCommittedEvent(Guid transactionId) - { - TransactionId = transactionId; - } - - public Guid TransactionId { get; } - } -} diff --git a/Src/RCommon.Persistence/Transactions/UnitOfWorkCompletedEvent.cs b/Src/RCommon.Persistence/Transactions/UnitOfWorkCompletedEvent.cs deleted file mode 100644 index a35c5a84..00000000 --- a/Src/RCommon.Persistence/Transactions/UnitOfWorkCompletedEvent.cs +++ /dev/null @@ -1,19 +0,0 @@ -using RCommon.EventHandling; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace RCommon.Persistence.Transactions -{ - public record UnitOfWorkCompletedEvent : ISyncEvent - { - public UnitOfWorkCompletedEvent(Guid transactionId) - { - TransactionId = transactionId; - } - - public Guid TransactionId { get; } - } -} diff --git a/Src/RCommon.Persistence/Transactions/UnitOfWorkCreatedEvent.cs b/Src/RCommon.Persistence/Transactions/UnitOfWorkCreatedEvent.cs deleted file mode 100644 index 8137bc31..00000000 --- a/Src/RCommon.Persistence/Transactions/UnitOfWorkCreatedEvent.cs +++ /dev/null @@ -1,20 +0,0 @@ -using RCommon.EventHandling; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Transactions; - -namespace RCommon.Persistence.Transactions -{ - public record UnitOfWorkCreatedEvent : ISyncEvent - { - public UnitOfWorkCreatedEvent(Guid transactionId) - { - TransactionId = transactionId; - } - - public Guid TransactionId { get; } - } -} diff --git a/Src/RCommon.Persistence/Transactions/UnitOfWorkFactory.cs b/Src/RCommon.Persistence/Transactions/UnitOfWorkFactory.cs index 2dbde401..9361bcfa 100644 --- a/Src/RCommon.Persistence/Transactions/UnitOfWorkFactory.cs +++ b/Src/RCommon.Persistence/Transactions/UnitOfWorkFactory.cs @@ -14,33 +14,29 @@ public class UnitOfWorkFactory : IUnitOfWorkFactory private readonly IEventBus _eventBus; private readonly IGuidGenerator _guidGenerator; - public UnitOfWorkFactory(IServiceProvider serviceProvider, IEventBus eventBus, IGuidGenerator guidGenerator) + public UnitOfWorkFactory(IServiceProvider serviceProvider, IGuidGenerator guidGenerator) { _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); - _eventBus = eventBus; _guidGenerator = guidGenerator; } - public async Task CreateAsync() + public IUnitOfWork Create() { var unitOfWork = _serviceProvider.GetService(); - await _eventBus.PublishAsync(new UnitOfWorkCreatedEvent(unitOfWork.TransactionId)); return unitOfWork; } - public async Task CreateAsync(TransactionMode transactionMode) + public IUnitOfWork Create(TransactionMode transactionMode) { var unitOfWork = _serviceProvider.GetService(); unitOfWork.TransactionMode = transactionMode; - await _eventBus.PublishAsync(new UnitOfWorkCreatedEvent(unitOfWork.TransactionId)); return unitOfWork; } - public async Task CreateAsync(TransactionMode transactionMode, IsolationLevel isolationLevel) + public IUnitOfWork Create(TransactionMode transactionMode, IsolationLevel isolationLevel) { var unitOfWork = _serviceProvider.GetService(); unitOfWork.TransactionMode = transactionMode; - await _eventBus.PublishAsync(new UnitOfWorkCreatedEvent(unitOfWork.TransactionId)); return unitOfWork; } } diff --git a/Src/RCommon.Persistence/Transactions/UnitOfWorkManager.cs b/Src/RCommon.Persistence/Transactions/UnitOfWorkManager.cs deleted file mode 100644 index d3eb232a..00000000 --- a/Src/RCommon.Persistence/Transactions/UnitOfWorkManager.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Threading.Tasks; -using System.Transactions; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using RCommon.EventHandling; - -namespace RCommon.Persistence.Transactions -{ - - public class UnitOfWorkManager : DisposableResource, IUnitOfWorkManager - { - private bool _disposed = false; - private ILogger _logger; - private readonly IEventBus _eventBus; - private readonly IDataStoreEnlistmentProvider _dataStoreEnlistmentProvider; - private IUnitOfWork _currentUnitOfWork; - private Guid _currentUnitOfWorkTransactionId; - - - public UnitOfWorkManager(ILogger logger, IEventBus eventBus, IDataStoreEnlistmentProvider dataStoreEnlistmentProvider) - { - _logger = logger; - _eventBus = eventBus; - _dataStoreEnlistmentProvider = dataStoreEnlistmentProvider; - } - - public bool EnlistUnitOfWork(IUnitOfWork unitOfWork) - { - _currentUnitOfWork = unitOfWork; - _currentUnitOfWorkTransactionId = unitOfWork.TransactionId; - _logger.LogInformation("UnitOfWork {0} Enlisted.", unitOfWork.TransactionId); - return true; - } - - public async Task CommitUnitOfWorkAsync(IUnitOfWork unitOfWork) - { - _logger.LogInformation("UnitOfWork {0} Comitting.", unitOfWork.TransactionId); - await FlushAsync(true, _dataStoreEnlistmentProvider.GetEnlistedDataStores(unitOfWork.TransactionId)); - _dataStoreEnlistmentProvider.RemoveEnlistedDataStores(unitOfWork.TransactionId); - await _eventBus.PublishAsync(new UnitOfWorkCommittedEvent(unitOfWork.TransactionId)); - } - - public async Task RollbackUnitOfWorkAsync(IUnitOfWork unitOfWork) - { - _logger.LogInformation("UnitOfWork {0} Rolling Back.", unitOfWork.TransactionId); - await _eventBus.PublishAsync(new UnitOfWorkRolledBackEvent(unitOfWork.TransactionId)); - } - - public async Task CompleteUnitOfWorkAsync(IUnitOfWork unitOfWork) - { - _logger.LogInformation("UnitOfWork {0} Completing.", unitOfWork.TransactionId); - _dataStoreEnlistmentProvider.RemoveEnlistedDataStores(unitOfWork.TransactionId); - await _eventBus.PublishAsync(new UnitOfWorkCompletedEvent(unitOfWork.TransactionId)); - } - - private async Task FlushAsync(bool allowPersist, IList dataStores) - { - if (dataStores.Count == 0) - { - throw new UnitOfWorkException("There were no enlisted data sources to persist changes against. This can happen when your repository is not enlisting data sources or if you instantiate repositories outside of a UnitOfWorkScope"); - } - - foreach (var item in dataStores) - { - if (allowPersist) - { - await item.PersistChangesAsync(); - } - } - } - - - [Obsolete("Please use UnitOfWorkManager.CurrentUnitOfWorkTransactionId. Public access will be removed in a future version and be limited to derived types.")] - public IUnitOfWork CurrentUnitOfWork - { - // This should get removed as it exposes the UnitOfWork to modification outside this class. - get - { - return _currentUnitOfWork; - } - } - - /// - /// Gets the current Transaction Id. - /// - public Guid CurrentUnitOfWorkTransactionId - { - get - { - return _currentUnitOfWorkTransactionId; - } - } - - public bool IsUnitOfWorkActive - { - get - { - return (_currentUnitOfWork == null ? false : true); - } - } - - protected override async Task DisposeAsync(bool disposing) - { - if (_disposed) - { - await Task.CompletedTask; - } - - if (disposing) - { - _disposed = true; - await this.DisposeAsync(); - } - } - } -} diff --git a/Src/RCommon.Persistence/Transactions/UnitOfWorkRolledBackEvent.cs b/Src/RCommon.Persistence/Transactions/UnitOfWorkRolledBackEvent.cs deleted file mode 100644 index 3701ad9e..00000000 --- a/Src/RCommon.Persistence/Transactions/UnitOfWorkRolledBackEvent.cs +++ /dev/null @@ -1,19 +0,0 @@ -using RCommon.EventHandling; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace RCommon.Persistence.Transactions -{ - public record UnitOfWorkRolledBackEvent : ISyncEvent - { - public UnitOfWorkRolledBackEvent(Guid transactionId) - { - TransactionId = transactionId; - } - - public Guid TransactionId { get; } - } -} diff --git a/Src/RCommon.Persistence/Transactions/UnitOfWorkState.cs b/Src/RCommon.Persistence/Transactions/UnitOfWorkState.cs index 4f15b6c9..74616706 100644 --- a/Src/RCommon.Persistence/Transactions/UnitOfWorkState.cs +++ b/Src/RCommon.Persistence/Transactions/UnitOfWorkState.cs @@ -8,7 +8,7 @@ namespace RCommon.Persistence.Transactions { public enum UnitOfWorkState { - Created =1, + Created = 1, CommitAttempted = 2, RolledBack = 3, Completed = 4, diff --git a/Tests/RCommon.Persistence.Dapper.Tests/DapperRepositoryIntegrationTests.cs b/Tests/RCommon.Persistence.Dapper.Tests/DapperRepositoryIntegrationTests.cs index 3bcf4b7d..c4393895 100644 --- a/Tests/RCommon.Persistence.Dapper.Tests/DapperRepositoryIntegrationTests.cs +++ b/Tests/RCommon.Persistence.Dapper.Tests/DapperRepositoryIntegrationTests.cs @@ -233,12 +233,12 @@ public async Task UnitOfWork_Can_Commit() var repo = new TestRepository(this.ServiceProvider); // Start Test - await using (var scope = await scopeFactory.CreateAsync()) + using (var scope = scopeFactory.Create()) { var customerRepo = this.ServiceProvider.GetService>(); await customerRepo.AddAsync(customer); - await scope.CommitAsync(); + scope.Commit(); } Customer savedCustomer = await repo.Context.Set() @@ -260,7 +260,7 @@ public async Task UnitOfWork_Can_Rollback() var scopeFactory = this.ServiceProvider.GetService(); var customerRepo = this.ServiceProvider.GetService>(); - await using (var scope = await scopeFactory.CreateAsync()) + using (var scope = scopeFactory.Create()) { //customer = await customerRepo.FindSingleOrDefaultAsync(x => x.Id == customer.Id); customer.LastName = "Changed"; @@ -283,18 +283,18 @@ public async Task UnitOfWork_Nested_Commit_Works() var scopeFactory = this.ServiceProvider.GetService(); var repo = new TestRepository(this.ServiceProvider); - await using (var scope = await scopeFactory.CreateAsync(TransactionMode.Default)) + using (var scope = scopeFactory.Create(TransactionMode.Default)) { var customerRepo = this.ServiceProvider.GetService>(); await customerRepo.AddAsync(customer); - await using (var scope2 = await scopeFactory.CreateAsync(TransactionMode.Default)) + using (var scope2 = scopeFactory.Create(TransactionMode.Default)) { var orderRepo = this.ServiceProvider.GetService>(); await orderRepo.AddAsync(order); - await scope2.CommitAsync(); + scope2.Commit(); } - await scope.CommitAsync(); + scope.Commit(); } Customer savedCustomer = null; @@ -319,16 +319,16 @@ public async Task UnitOfWork_Nested_Rollback_Works() var scopeFactory = this.ServiceProvider.GetService(); var repo = new TestRepository(this.ServiceProvider); - await using (var scope = await scopeFactory.CreateAsync(TransactionMode.Default)) + using (var scope = scopeFactory.Create(TransactionMode.Default)) { var customerRepo = this.ServiceProvider.GetService>(); await customerRepo.AddAsync(customer); - await using (var scope2 = await scopeFactory.CreateAsync(TransactionMode.Default)) + using (var scope2 = scopeFactory.Create(TransactionMode.Default)) { var orderRepo = this.ServiceProvider.GetService>(); await orderRepo.AddAsync(order); - await scope2.CommitAsync(); + scope2.Commit(); } } //Rollback. @@ -355,13 +355,13 @@ public async Task UnitOfWork_Commit_Throws_When_Child_Scope_Rollsback() try { - await using (var scope = await scopeFactory.CreateAsync()) + using (var scope = scopeFactory.Create()) { var customerRepo = this.ServiceProvider.GetService>(); var salesPersonRepo = this.ServiceProvider.GetService>(); await customerRepo.AddAsync(customer); - await using (var scope2 = await scopeFactory.CreateAsync()) + using (var scope2 = scopeFactory.Create()) { await salesPersonRepo.AddAsync(salesPerson); } //child scope rollback. @@ -387,14 +387,14 @@ public async Task UnitOfWork_Can_Commit_Multiple_Db_Operations() // Setup required services var scopeFactory = this.ServiceProvider.GetService(); - await using (var scope = await scopeFactory.CreateAsync(TransactionMode.Default)) + using (var scope = scopeFactory.Create(TransactionMode.Default)) { var customerRepo = this.ServiceProvider.GetService>(); var salesPersonRepo = this.ServiceProvider.GetService>(); await customerRepo.AddAsync(customer); await salesPersonRepo.AddAsync(salesPerson); - await scope.CommitAsync(); + scope.Commit(); } @@ -421,7 +421,7 @@ public async Task UnitOfWork_Can_Rollback_Multipe_Db_Operations() var repo = new TestRepository(this.ServiceProvider); - await using (var scope = await scopeFactory.CreateAsync(TransactionMode.Default)) + using (var scope = scopeFactory.Create(TransactionMode.Default)) { var customerRepo = this.ServiceProvider.GetService>(); var salesPersonRepo = this.ServiceProvider.GetService>(); diff --git a/Tests/RCommon.Persistence.Dapper.Tests/TestDbConnection.cs b/Tests/RCommon.Persistence.Dapper.Tests/TestDbConnection.cs index 0204b6f5..43a6c65c 100644 --- a/Tests/RCommon.Persistence.Dapper.Tests/TestDbConnection.cs +++ b/Tests/RCommon.Persistence.Dapper.Tests/TestDbConnection.cs @@ -11,8 +11,8 @@ namespace RCommon.Persistence.Dapper.Tests public class TestDbConnection : RDbConnection { - public TestDbConnection(IOptions options, IEntityEventTracker eventTracker) - : base(options, eventTracker) + public TestDbConnection(IOptions options) + : base(options) { } diff --git a/Tests/RCommon.Persistence.EFCore.Tests/EFCoreRepositoryIntegrationTests.cs b/Tests/RCommon.Persistence.EFCore.Tests/EFCoreRepositoryIntegrationTests.cs index c26a7c61..8ada7d44 100644 --- a/Tests/RCommon.Persistence.EFCore.Tests/EFCoreRepositoryIntegrationTests.cs +++ b/Tests/RCommon.Persistence.EFCore.Tests/EFCoreRepositoryIntegrationTests.cs @@ -341,12 +341,12 @@ public async Task UnitOfWork_Can_Commit() var repo = new TestRepository(this.ServiceProvider); // Start Test - await using (var scope = await scopeFactory.CreateAsync()) + using (var scope = scopeFactory.Create()) { var customerRepo = this.ServiceProvider.GetService>(); await customerRepo.AddAsync(customer); - await scope.CommitAsync(); + scope.Commit(); } Customer savedCustomer = await repo.Context.Set() @@ -368,13 +368,13 @@ public async Task UnitOfWork_Can_Rollback() var scopeFactory = this.ServiceProvider.GetService(); var customerRepo = this.ServiceProvider.GetService>(); - await using (var scope = await scopeFactory.CreateAsync()) + using (var scope = scopeFactory.Create()) { - customer = await customerRepo.FirstAsync(x=>x.Id == customer.Id); + customer = await customerRepo.FirstAsync(x => x.Id == customer.Id); customer.LastName = "Changed"; await customerRepo.UpdateAsync(customer); - - } //Dispose here as scope is not comitted. + } + /*}*/ //Rollback here as scope is not comitted. Customer savedCustomer = null; savedCustomer = await repo.Context.Set().AsNoTracking().FirstAsync(x=>x.Id == customer.Id); @@ -392,18 +392,18 @@ public async Task UnitOfWork_Nested_Commit_Works() var scopeFactory = this.ServiceProvider.GetService(); var repo = new TestRepository(this.ServiceProvider); - await using (var scope = await scopeFactory.CreateAsync(TransactionMode.Default)) + using (var scope = scopeFactory.Create(TransactionMode.Default)) { var customerRepo = this.ServiceProvider.GetService>(); await customerRepo.AddAsync(customer); - await using (var scope2 = await scopeFactory.CreateAsync(TransactionMode.Default)) + using (var scope2 = scopeFactory.Create(TransactionMode.Default)) { var orderRepo = this.ServiceProvider.GetService>(); await orderRepo.AddAsync(order); - await scope2.CommitAsync(); + scope2.Commit(); } - await scope.CommitAsync(); + scope.Commit(); } Customer savedCustomer = null; @@ -438,7 +438,7 @@ public async Task UnitOfWork_Nested_Commit_Works() // var repo = new TestRepository(this.ServiceProvider); // this.Logger.LogInformation("Starting initial UnitOfWorkScope from {0}", MethodBase.GetCurrentMethod()); - // await using (var scope = await scopeFactory.CreateAsync(TransactionMode.Default)) + // using (var scope = scopeFactory.Create(TransactionMode.Default)) // { // var customerRepo = this.ServiceProvider.GetService>(); @@ -481,16 +481,16 @@ public async Task UnitOfWork_Nested_Rollback_Works() var scopeFactory = this.ServiceProvider.GetService(); var repo = new TestRepository(this.ServiceProvider); - await using (var scope = await scopeFactory.CreateAsync(TransactionMode.Default)) + using (var scope = scopeFactory.Create(TransactionMode.Default)) { var customerRepo = this.ServiceProvider.GetService>(); await customerRepo.AddAsync(customer); - await using (var scope2 = await scopeFactory.CreateAsync(TransactionMode.Default)) + using (var scope2 = scopeFactory.Create(TransactionMode.Default)) { var orderRepo = this.ServiceProvider.GetService>(); await orderRepo.AddAsync(order); - await scope2.CommitAsync(); + scope2.Commit(); } } //Rollback. @@ -519,10 +519,10 @@ public async Task UnitOfWork_Commit_Throws_When_Child_Scope_Rollsback() try { - await using (var scope = await scopeFactory.CreateAsync()) + using (var scope = scopeFactory.Create()) { await customerRepo.AddAsync(customer); - await using (var scope2 = await scopeFactory.CreateAsync()) + using (var scope2 = scopeFactory.Create()) { await salesPersonRepo.AddAsync(salesPerson); } //child scope rollback. @@ -548,14 +548,14 @@ public async Task UnitOfWork_Can_Commit_Multiple_Db_Operations() // Setup required services var scopeFactory = this.ServiceProvider.GetService(); - await using (var scope = await scopeFactory.CreateAsync(TransactionMode.Default)) + using (var scope = scopeFactory.Create(TransactionMode.Default)) { var customerRepo = this.ServiceProvider.GetService>(); var salesPersonRepo = this.ServiceProvider.GetService>(); await customerRepo.AddAsync(customer); await salesPersonRepo.AddAsync(salesPerson); - await scope.CommitAsync(); + scope.Commit(); } @@ -582,7 +582,7 @@ public async Task UnitOfWork_Can_Rollback_Multipe_Db_Operations() var repo = new TestRepository(this.ServiceProvider); - await using (var scope = await scopeFactory.CreateAsync(TransactionMode.Default)) + using (var scope = scopeFactory.Create(TransactionMode.Default)) { var customerRepo = this.ServiceProvider.GetService>(); var salesPersonRepo = this.ServiceProvider.GetService>(); @@ -619,7 +619,7 @@ public async Task UnitOfWork_Can_Rollback_Multipe_Db_Operations() // var repo = new TestRepository(this.ServiceProvider); - // await using (var scope = await scopeFactory.CreateAsync(TransactionMode.Default)) + // using (var scope = scopeFactory.Create(TransactionMode.Default)) // { // var customerRepo = this.ServiceProvider.GetService>(); // await customerRepo.AddAsync(customer); diff --git a/Tests/RCommon.Persistence.Linq2Db.Tests/Linq2DbRepositoryIntegrationTests.cs b/Tests/RCommon.Persistence.Linq2Db.Tests/Linq2DbRepositoryIntegrationTests.cs index e59b9fee..99ccfcd8 100644 --- a/Tests/RCommon.Persistence.Linq2Db.Tests/Linq2DbRepositoryIntegrationTests.cs +++ b/Tests/RCommon.Persistence.Linq2Db.Tests/Linq2DbRepositoryIntegrationTests.cs @@ -22,7 +22,7 @@ namespace RCommon.Persistence.Linq2Db.Tests [TestFixture()] public class Linq2DbRepositoryIntegrationTests : Linq2DbTestBase { - private IDataStoreRegistry _dataStoreRegistry; + private IDataStoreFactory _dataStoreFactory; public Linq2DbRepositoryIntegrationTests() : base() @@ -312,12 +312,12 @@ public async Task UnitOfWork_Can_Commit() var repo = new TestRepository(this.ServiceProvider); // Start Test - await using (var scope = await scopeFactory.CreateAsync()) + using (var scope = scopeFactory.Create()) { var customerRepo = this.ServiceProvider.GetService>(); await customerRepo.AddAsync(customer); - await scope.CommitAsync(); + scope.Commit(); } Customer savedCustomer = await repo.Context.Set() @@ -337,7 +337,7 @@ public async Task UnitOfWork_Can_Rollback() var scopeFactory = this.ServiceProvider.GetService(); var customerRepo = this.ServiceProvider.GetService>(); - await using (var scope = await scopeFactory.CreateAsync()) + using (var scope = scopeFactory.Create()) { customer = await customerRepo.FirstAsync(x => x.Id == customer.Id); customer.LastName = "Changed"; @@ -361,18 +361,18 @@ public async Task UnitOfWork_Nested_Commit_Works() var scopeFactory = this.ServiceProvider.GetService(); var repo = new TestRepository(this.ServiceProvider); - await using (var scope = await scopeFactory.CreateAsync(TransactionMode.Default)) + using (var scope = scopeFactory.Create(TransactionMode.Default)) { var customerRepo = this.ServiceProvider.GetService>(); await customerRepo.AddAsync(customer); - await using (var scope2 = await scopeFactory.CreateAsync(TransactionMode.Default)) + using (var scope2 = scopeFactory.Create(TransactionMode.Default)) { var orderRepo = this.ServiceProvider.GetService>(); await orderRepo.AddAsync(order); - await scope2.CommitAsync(); + scope2.Commit(); } - await scope.CommitAsync(); + scope.Commit(); } Customer savedCustomer = null; @@ -395,16 +395,16 @@ public async Task UnitOfWork_Nested_Rollback_Works() var scopeFactory = this.ServiceProvider.GetService(); var repo = new TestRepository(this.ServiceProvider); - await using (var scope = await scopeFactory.CreateAsync(TransactionMode.Default)) + using (var scope = scopeFactory.Create(TransactionMode.Default)) { var customerRepo = this.ServiceProvider.GetService>(); await customerRepo.AddAsync(customer); - await using (var scope2 = await scopeFactory.CreateAsync(TransactionMode.Default)) + using (var scope2 = scopeFactory.Create(TransactionMode.Default)) { var orderRepo = this.ServiceProvider.GetService>(); await orderRepo.AddAsync(order); - await scope2.CommitAsync(); + scope2.Commit(); } } //Rollback. @@ -433,10 +433,10 @@ public async Task UnitOfWork_Commit_Throws_When_Child_Scope_Rollsback() try { - await using (var scope = await scopeFactory.CreateAsync()) + using (var scope = scopeFactory.Create()) { await customerRepo.AddAsync(customer); - await using (var scope2 = await scopeFactory.CreateAsync()) + using (var scope2 = scopeFactory.Create()) { await salesPersonRepo.AddAsync(salesPerson); } //child scope rollback. @@ -462,14 +462,14 @@ public async Task UnitOfWork_Can_Commit_Multiple_Db_Operations() // Setup required services var scopeFactory = this.ServiceProvider.GetService(); - await using (var scope = await scopeFactory.CreateAsync(TransactionMode.Default)) + using (var scope = scopeFactory.Create(TransactionMode.Default)) { var customerRepo = this.ServiceProvider.GetService>(); var salesPersonRepo = this.ServiceProvider.GetService>(); await customerRepo.AddAsync(customer); await salesPersonRepo.AddAsync(salesPerson); - await scope.CommitAsync(); + scope.Commit(); } @@ -494,7 +494,7 @@ public async Task UnitOfWork_Can_Rollback_Multipe_Db_Operations() var repo = new TestRepository(this.ServiceProvider); - await using (var scope = await scopeFactory.CreateAsync(TransactionMode.Default)) + using (var scope = scopeFactory.Create(TransactionMode.Default)) { var customerRepo = this.ServiceProvider.GetService>(); var salesPersonRepo = this.ServiceProvider.GetService>(); diff --git a/Tests/RCommon.TestBase.Data/EFConfigurations/TestDbContext.cs b/Tests/RCommon.TestBase.Data/EFConfigurations/TestDbContext.cs index 031031a6..025d5ec0 100644 --- a/Tests/RCommon.TestBase.Data/EFConfigurations/TestDbContext.cs +++ b/Tests/RCommon.TestBase.Data/EFConfigurations/TestDbContext.cs @@ -42,8 +42,7 @@ public class TestDbContext : RCommonDbContext private readonly IConfiguration _configuration; - public TestDbContext(DbContextOptions options, IConfiguration configuration, - IEntityEventTracker eventTracker) : base(options, eventTracker) + public TestDbContext(DbContextOptions options, IConfiguration configuration) : base(options) { _configuration = configuration; } diff --git a/Tests/RCommon.TestBase.Data/TestRepository.cs b/Tests/RCommon.TestBase.Data/TestRepository.cs index 04616f27..f4dceec5 100644 --- a/Tests/RCommon.TestBase.Data/TestRepository.cs +++ b/Tests/RCommon.TestBase.Data/TestRepository.cs @@ -18,7 +18,7 @@ public class TestRepository { readonly DbContext _context; readonly IList> _entityDeleteActions; - private IDataStoreRegistry _dataStoreRegistry; + private IDataStoreFactory _dataStoreFactory; public TestRepository(DbContext context) { @@ -28,8 +28,8 @@ public TestRepository(DbContext context) public TestRepository(ServiceProvider serviceProvider) { - _dataStoreRegistry = serviceProvider.GetService(); - _context = _dataStoreRegistry.GetDataStore("TestDbContext"); + _dataStoreFactory = serviceProvider.GetService(); + _context = _dataStoreFactory.Resolve("TestDbContext"); _entityDeleteActions = new List>(); }