/// <summary> /// Encapsulates several repository calls with one DbContext. Any exceptions thrown inside will end up rolling back all repository transactions. /// /// To change a repository's context to use unitOfWork's localContext, make sure to call /// <c>rRegistrar.ConvertContextOfRepository(myRepo).ToUse(localContext);</c> /// </summary> /// /// <param name="repoWork">Asynchronous lambda to do the repository transactions</param> public async Task RunAsync(RepoWorkAsync repoWork) { RepositoryRegistry rRegistry = new RepositoryRegistry(); RepositoryRegistryRegistrar rRegistrar = new RepositoryRegistryRegistrar(rRegistry); ConcertoDbContext localContext = null; try { using (var scope = serviceProvider.CreateScope()) { localContext = scope.ServiceProvider.GetService <ConcertoDbContext>(); localContext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; using (var trans = localContext.Database.BeginTransaction()) { try { await repoWork(rRegistrar, localContext); trans.Commit(); } catch (Exception e) { trans.Rollback(); throw e; } } } } catch (Exception e) { throw e; } finally { /** * Convert All DbContexts of all repositories registered in registry */ rRegistry.GetRepositories().ForEach(unitOfWorkRepository => unitOfWorkRepository.RevertToPreviousDbContext()); rRegistry.Clear(); } }
public void RevertToPreviousDbContext() { this.Context = PrevDbContext; PrevDbContext = null; }
public void UseContext(DbContext context) { PrevDbContext = this.Context; this.Context = (ConcertoDbContext)context; }
// For EntityFrameworkCore, extend from this ctor public BaseRepository(IDbContextFactory dbContextFactory) { Context = (ConcertoDbContext)dbContextFactory.GetContext(); }
public void ToUse(ConcertoDbContext context) { repositoryRegistry.AddRepo(repository); repository.UseContext(context); }