public async Task CommitAsync_WithoutCancellationTokenInNestedUow_SavedChangesInParentUow() { var dbContext = new Mock <DbContext>(); Func <DbContext> dbContextFactory = () => dbContext.Object; var unitOfWorkRegistryStub = new ThreadLocalUnitOfWorkRegistry(); var unitOfWorkProvider = new EntityFrameworkUnitOfWorkProvider(unitOfWorkRegistryStub, dbContextFactory); using (var uow = unitOfWorkProvider.Create()) { using (var nested = unitOfWorkProvider.Create()) { await nested.CommitAsync(); // verify, that method has NEVER been called dbContext.Verify(x => x.SaveChangesAsync(It.IsAny <CancellationToken>()), Times.Never); } await uow.CommitAsync(); // verify, that method has been called ONCE dbContext.Verify(x => x.SaveChangesAsync(It.IsAny <CancellationToken>()), Times.Once); } }
public void Commit_CorrectChildRequestIgnoredBehavior() { Func <DbContext> dbContextFactory = () => new Mock <DbContext>().Object; var unitOfWorkRegistryStub = new ThreadLocalUnitOfWorkRegistry(); var unitOfWorkProvider = new EntityFrameworkUnitOfWorkProvider(unitOfWorkRegistryStub, dbContextFactory); Assert.Throws <ChildCommitPendingException>(() => { using (unitOfWorkProvider.Create(DbContextOptions.ReuseParentContext)) { using (var unitOfWorkChild = unitOfWorkProvider.Create(DbContextOptions.ReuseParentContext)) { unitOfWorkChild.Commit(); } } }); // test that unit of work provider keeps working after caught exception using (unitOfWorkProvider.Create(DbContextOptions.ReuseParentContext)) { using (unitOfWorkProvider.Create(DbContextOptions.ReuseParentContext)) { } } }
public async Task Commit_Transaction_CallRollback_UserCatch() { var dbContextFactory = GetContextFactory(); var unitOfWorkRegistryStub = new ThreadLocalUnitOfWorkRegistry(); var unitOfWorkProvider = new EntityFrameworkUnitOfWorkProvider <InMemoryDbContext>(unitOfWorkRegistryStub, dbContextFactory); var scopeMock = new Mock <UnitOfWorkTransactionScope <InMemoryDbContext> >(unitOfWorkProvider); var scope = scopeMock.Object; await scope.ExecuteAsync(async uowParent => { Assert.True(uowParent.IsInTransaction); await uowParent.CommitAsync(); using (var uowChild = (EntityFrameworkUnitOfWork <InMemoryDbContext>)unitOfWorkProvider.Create()) { await uowChild.CommitAsync(); try { uowParent.RollbackTransaction(); } catch (Exception) { // user catches any exceptions } } }); scopeMock.Protected().Verify("AfterRollback", Times.Once()); }
public async Task Commit_Transaction_CallRollback_OnException() { var dbContextFactory = GetContextFactory(); var unitOfWorkRegistryStub = new ThreadLocalUnitOfWorkRegistry(); var unitOfWorkProvider = new EntityFrameworkUnitOfWorkProvider <InMemoryDbContext>(unitOfWorkRegistryStub, dbContextFactory); var scope = unitOfWorkProvider.CreateTransactionScope(); var exceptionKey = Guid.NewGuid().ToString(); try { await scope.ExecuteAsync(async uowParent => { Assert.True(uowParent.IsInTransaction); await uowParent.CommitAsync(); throw new Exception(exceptionKey); }); } catch (Exception e) when(e.Message == exceptionKey) { // test exception caught, passed } }
public async Task Commit_UOWHasChild_CallCommitCore() { Func <DbContext> dbContextFactory = () => new Mock <DbContext>().Object; var unitOfWorkRegistryStub = new ThreadLocalUnitOfWorkRegistry(); var unitOfWorkProvider = new EntityFrameworkUnitOfWorkProvider(unitOfWorkRegistryStub, dbContextFactory); var unitOfWorkParentMock = new Mock <EntityFrameworkUnitOfWork>(unitOfWorkProvider, dbContextFactory, DbContextOptions.ReuseParentContext) { CallBase = true }; using (var unitOfWorkParent = unitOfWorkParentMock.Object) { unitOfWorkRegistryStub.RegisterUnitOfWork(unitOfWorkParent); using (var unitOfWorkChild = new EntityFrameworkUnitOfWork(unitOfWorkProvider, dbContextFactory, DbContextOptions.ReuseParentContext)) { await unitOfWorkChild.CommitAsync(); } await unitOfWorkParent.CommitAsync(); } unitOfWorkParentMock.Protected().Verify("CommitAsyncCore", Times.Once(), new CancellationToken()); }
public void Commit_CallCommitCoreOnlyIfHasOwnDbContext() { Func <DbContext> dbContextFactory = () => new Mock <DbContext>().Object; var unitOfWorkRegistryStub = new ThreadLocalUnitOfWorkRegistry(); var unitOfWorkProvider = new EntityFrameworkUnitOfWorkProvider(unitOfWorkRegistryStub, dbContextFactory); var unitOfWorkParentMock = new Mock <EntityFrameworkUnitOfWork>(unitOfWorkProvider, dbContextFactory, DbContextOptions.ReuseParentContext) { CallBase = true }; using (var unitOfWorkParent = unitOfWorkParentMock.Object) { unitOfWorkRegistryStub.RegisterUnitOfWork(unitOfWorkParent); var unitOfWorkChildMock = new Mock <EntityFrameworkUnitOfWork>(unitOfWorkProvider, dbContextFactory, DbContextOptions.ReuseParentContext) { CallBase = true }; using (var unitOfWorkChild = unitOfWorkChildMock.Object) { unitOfWorkChild.Commit(); } unitOfWorkChildMock.Protected().Verify("CommitCore", Times.Never()); unitOfWorkParent.Commit(); } unitOfWorkParentMock.Protected().Verify("CommitCore", Times.Once()); }
public async Task CommitAsync_ThrowIfChildCommitRequestedNotFulfilledByRoot() { Func <DbContext> dbContextFactory = () => new Mock <DbContext>().Object; var unitOfWorkRegistryStub = new ThreadLocalUnitOfWorkRegistry(); var unitOfWorkProvider = new EntityFrameworkUnitOfWorkProvider(unitOfWorkRegistryStub, dbContextFactory); await Assert.ThrowsAsync <ChildCommitPendingException>(async() => { using (unitOfWorkProvider.Create(DbContextOptions.ReuseParentContext)) { using (var unitOfWorkChild = unitOfWorkProvider.Create(DbContextOptions.ReuseParentContext)) { await unitOfWorkChild.CommitAsync(); } } }); // test that unit of work provider keeps working after caught exception using (unitOfWorkProvider.Create(DbContextOptions.ReuseParentContext)) { using (unitOfWorkProvider.Create(DbContextOptions.ReuseParentContext)) { } } }
public void TryGetDbContext_UnitOfWorkRegistryHasNotUnitOfWork_ReturnsNull() { var dbContext = new Mock <DbContext>().Object; Func <DbContext> dbContextFactory = () => dbContext; var unitOfWorkRegistryStub = new ThreadLocalUnitOfWorkRegistry(); var unitOfWorkProvider = new EntityFrameworkUnitOfWorkProvider(unitOfWorkRegistryStub, dbContextFactory); var value = EntityFrameworkUnitOfWork.TryGetDbContext(unitOfWorkProvider); Assert.Null(value); }
private EntityFrameworkRepository <TEntity, int> CreateEntityFrameworkRepository <TEntity>() where TEntity : class, IEntity <int>, new() { var unitOfWorkRegistryStub = new ThreadLocalUnitOfWorkRegistry(); var unitOfWorkProvider = new EntityFrameworkUnitOfWorkProvider(unitOfWorkRegistryStub, CreateYesMinisterDbContext); IDateTimeProvider dateTimeProvider = new UtcDateTimeProvider(); var unitOfWork = new EntityFrameworkUnitOfWork(unitOfWorkProvider, CreateYesMinisterDbContext, DbContextOptions.ReuseParentContext); unitOfWorkRegistryStub.RegisterUnitOfWork(unitOfWork); return(new EntityFrameworkRepository <TEntity, int>(unitOfWorkProvider, dateTimeProvider)); }
public void TryGetDbContext_UnitOfWorkRegistryHasUnitOfWork_ReturnCorrectDbContext() { var dbContext = new Mock <DbContext>().Object; Func <DbContext> dbContextFactory = () => dbContext; var unitOfWorkRegistryStub = new ThreadLocalUnitOfWorkRegistry(); var unitOfWorkProvider = new EntityFrameworkUnitOfWorkProvider(unitOfWorkRegistryStub, dbContextFactory); var unitOfWork = new EntityFrameworkUnitOfWork(unitOfWorkProvider, dbContextFactory, DbContextOptions.ReuseParentContext); unitOfWorkRegistryStub.RegisterUnitOfWork(unitOfWork); var uowDbContext = EntityFrameworkUnitOfWork.TryGetDbContext(unitOfWorkProvider); Assert.NotNull(uowDbContext); Assert.Same(dbContext, uowDbContext); }
public void Commit_CorrectMultipleLayeredReuseParentBehavior() { Func <DbContext> dbContextFactory = () => new Mock <DbContext>().Object; var unitOfWorkRegistryStub = new ThreadLocalUnitOfWorkRegistry(); var unitOfWorkProvider = new EntityFrameworkUnitOfWorkProvider(unitOfWorkRegistryStub, dbContextFactory); using (var unitOfWorkParent = unitOfWorkProvider.Create(DbContextOptions.ReuseParentContext)) { // 1st level, context 1 using (unitOfWorkProvider.Create(DbContextOptions.ReuseParentContext)) { // 2nd level, context 1 using (unitOfWorkProvider.Create(DbContextOptions.AlwaysCreateOwnContext)) { // 3rd level, context 2 using (unitOfWorkProvider.Create(DbContextOptions.ReuseParentContext)) { // 4th level, context 2 using (var unitOfWorkParent3 = unitOfWorkProvider.Create(DbContextOptions.AlwaysCreateOwnContext)) { // 5th level, context 3 using (unitOfWorkProvider.Create(DbContextOptions.ReuseParentContext)) { // 6th level, context 3 using (unitOfWorkProvider.Create(DbContextOptions.ReuseParentContext)) { } using (var unitOfWorkChild3 = unitOfWorkProvider.Create(DbContextOptions.ReuseParentContext)) { // 7th level, context 3 commit requested unitOfWorkChild3.Commit(); } } // commit mandatory, context 3 commit pending unitOfWorkParent3.Commit(); } } } } // commit optional, no reusing child commit pending unitOfWorkParent.Commit(); } }
public async Task Commit_Transaction_CallCommit_Nesting() { var dbContextFactory = GetContextFactory(); var unitOfWorkRegistryStub = new ThreadLocalUnitOfWorkRegistry(); var unitOfWorkProvider = new EntityFrameworkUnitOfWorkProvider <InMemoryDbContext>(unitOfWorkRegistryStub, dbContextFactory); var scopeMock = new Mock <UnitOfWorkTransactionScope <InMemoryDbContext> >(unitOfWorkProvider); var scope = scopeMock.Object; await scope.ExecuteAsync(async uowParent => { Assert.True(uowParent.IsInTransaction); await uowParent.CommitAsync(); Assert.Equal(1, uowParent.CommitsCount); Assert.False(uowParent.CommitPending); using (var uowChild = (EntityFrameworkUnitOfWork <InMemoryDbContext>)unitOfWorkProvider.Create()) { await uowChild.CommitAsync(); Assert.Equal(1, uowChild.CommitsCount); Assert.False(uowChild.CommitPending); Assert.Equal(2, uowParent.CommitsCount); Assert.False(uowParent.CommitPending); using (var uowChildChild = (EntityFrameworkUnitOfWork <InMemoryDbContext>)unitOfWorkProvider.Create()) { await uowChildChild.CommitAsync(); } Assert.Equal(2, uowChild.CommitsCount); Assert.False(uowChild.CommitPending); Assert.Equal(3, uowParent.CommitsCount); Assert.False(uowParent.CommitPending); } }); scopeMock.Protected().Verify("AfterCommit", Times.Once()); }
public void Commit_Transaction_CallCommit_Sync() { var dbContextFactory = GetContextFactory(); var unitOfWorkRegistryStub = new ThreadLocalUnitOfWorkRegistry(); var unitOfWorkProvider = new EntityFrameworkUnitOfWorkProvider <InMemoryDbContext>(unitOfWorkRegistryStub, dbContextFactory); var scopeMock = new Mock <UnitOfWorkTransactionScope <InMemoryDbContext> >(unitOfWorkProvider); var scope = scopeMock.Object; scope.Execute(uowParent => { Assert.True(uowParent.IsInTransaction); uowParent.Commit(); Assert.Equal(1, uowParent.CommitsCount); Assert.False(uowParent.CommitPending); }); scopeMock.Protected().Verify("AfterCommit", Times.Once()); }
public void NestedDbContexts() { var registry = new ThreadLocalUnitOfWorkRegistry(); var uowp1 = new EntityFrameworkUnitOfWorkProvider <CustomDbContext1>(registry, () => new CustomDbContext1()); var uowp2 = new EntityFrameworkUnitOfWorkProvider <CustomDbContext2>(registry, () => new CustomDbContext2()); using (var uow1 = uowp1.Create()) { using (var uow2 = uowp2.Create()) { var current = registry.GetCurrent(0); Assert.Equal(uow2, current); var parent = registry.GetCurrent(1); Assert.Equal(uow1, parent); var inner = EntityFrameworkUnitOfWork.TryGetDbContext <CustomDbContext2>(uowp2); Assert.Equal(((EntityFrameworkUnitOfWork <CustomDbContext2>)uow2).Context, inner); var outer = EntityFrameworkUnitOfWork.TryGetDbContext <CustomDbContext1>(uowp1); Assert.Equal(((EntityFrameworkUnitOfWork <CustomDbContext1>)uow1).Context, outer); } } }