public void TransactionHandler_is_disposed_even_if_the_context_is_not() { var context = new BlogContextCommit(); context.Database.Delete(); Assert.Equal(1, context.Blogs.Count()); var weakDbContext = new WeakReference(context); var weakObjectContext = new WeakReference(((IObjectContextAdapter)context).ObjectContext); var weakTransactionHandler = new WeakReference(((IObjectContextAdapter)context).ObjectContext.TransactionHandler); context = null; GC.Collect(); GC.WaitForPendingFinalizers(); Assert.False(weakDbContext.IsAlive); Assert.False(weakObjectContext.IsAlive); DbDispatchersHelpers.AssertNoInterceptors(); // Need a second pass as the TransactionHandler is removed from the interceptors in the ObjectContext finalizer GC.Collect(); Assert.False(weakTransactionHandler.IsAlive); }
private void TransactionHandler_and_ExecutionStrategy_does_not_retry_on_false_commit_fail_implementation( Action <BlogContextCommit> runAndVerify) { var failingTransactionInterceptorMock = new Mock <FailingTransactionInterceptor> { CallBase = true }; var failingTransactionInterceptor = failingTransactionInterceptorMock.Object; DbInterception.Add(failingTransactionInterceptor); MutableResolver.AddResolver <Func <IDbExecutionStrategy> >( key => (Func <IDbExecutionStrategy>) (() => new SqlAzureExecutionStrategy(maxRetryCount: 2, maxDelay: TimeSpan.FromMilliseconds(1)))); try { using (var context = new BlogContextCommit()) { failingTransactionInterceptor.ShouldFailTimes = 0; context.Database.Delete(); Assert.Equal(1, context.Blogs.Count()); failingTransactionInterceptor.ShouldFailTimes = 2; failingTransactionInterceptor.ShouldRollBack = false; context.Blogs.Add(new BlogContext.Blog()); runAndVerify(context); failingTransactionInterceptorMock.Verify( m => m.Committing(It.IsAny <DbTransaction>(), It.IsAny <DbTransactionInterceptionContext>()), Times.Exactly(3)); } using (var context = new BlogContextCommit()) { Assert.Equal(2, context.Blogs.Count()); using (var transactionContext = new TransactionContext(context.Database.Connection)) { using (var infoContext = GetInfoContext(transactionContext)) { Assert.True( !infoContext.TableExists("__Transactions") || !transactionContext.Transactions.Any()); } } } } finally { DbInterception.Remove(failingTransactionInterceptorMock.Object); MutableResolver.ClearResolvers(); } DbDispatchersHelpers.AssertNoInterceptors(); }
public void CommitFailureHandler_supports_nested_transactions() { MutableResolver.AddResolver <Func <TransactionHandler> >( new TransactionHandlerResolver(() => new CommitFailureHandler(), null, null)); try { using (var context = new BlogContextCommit()) { ExtendedSqlAzureExecutionStrategy.ExecuteNew( () => { context.Database.Delete(); Assert.Equal(1, context.Blogs.Count()); }); context.Blogs.Add(new BlogContext.Blog()); ExtendedSqlAzureExecutionStrategy.ExecuteNew( () => { using (var transaction = context.Database.BeginTransaction()) { using (var innerContext = new BlogContextCommit()) { using (var innerTransaction = innerContext.Database.BeginTransaction()) { Assert.Equal(1, innerContext.Blogs.Count()); innerContext.Blogs.Add(new BlogContext.Blog()); innerContext.SaveChanges(); innerTransaction.Commit(); } } context.SaveChanges(); transaction.Commit(); } }); } ExtendedSqlAzureExecutionStrategy.ExecuteNew( () => { using (var context = new BlogContextCommit()) { Assert.Equal(3, context.Blogs.Count()); } }); } finally { MutableResolver.ClearResolvers(); } DbDispatchersHelpers.AssertNoInterceptors(); }
private static void CreateContext( out WeakReference weakDbContext, out WeakReference weakObjectContext, out WeakReference weakTransactionHandler) { var context = new BlogContextCommit(); context.Database.Delete(); Assert.Equal(1, context.Blogs.Count()); weakDbContext = new WeakReference(context); weakObjectContext = new WeakReference(((IObjectContextAdapter)context).ObjectContext); weakTransactionHandler = new WeakReference(((IObjectContextAdapter)context).ObjectContext.TransactionHandler); }
private void CommitFailureHandler_prunes_transactions_after_set_amount_implementation(bool shouldThrow) { var failingTransactionInterceptor = new FailingTransactionInterceptor(); DbInterception.Add(failingTransactionInterceptor); MutableResolver.AddResolver <Func <TransactionHandler> >( new TransactionHandlerResolver(() => new MyCommitFailureHandler(c => new TransactionContext(c)), null, null)); try { using (var context = new BlogContextCommit()) { context.Database.Delete(); Assert.Equal(1, context.Blogs.Count()); var objectContext = ((IObjectContextAdapter)context).ObjectContext; var transactionHandler = (MyCommitFailureHandler)objectContext.TransactionHandler; for (var i = 0; i < transactionHandler.PruningLimit; i++) { context.Blogs.Add(new BlogContext.Blog()); context.SaveChanges(); } AssertTransactionHistoryCount(context, transactionHandler.PruningLimit); if (shouldThrow) { failingTransactionInterceptor.ShouldFailTimes = 1; failingTransactionInterceptor.ShouldRollBack = false; } context.Blogs.Add(new BlogContext.Blog()); context.SaveChanges(); context.Blogs.Add(new BlogContext.Blog()); context.SaveChanges(); AssertTransactionHistoryCount(context, 1); Assert.Equal(1, transactionHandler.TransactionContext.ChangeTracker.Entries <TransactionRow>().Count()); } } finally { DbInterception.Remove(failingTransactionInterceptor); MutableResolver.ClearResolvers(); } DbDispatchersHelpers.AssertNoInterceptors(); }
private static void Execute_commit_failure_test( Action <BlogContextCommit> runAndVerify, int expectedBlogs, bool useTransactionHandler, bool useExecutionStrategy, bool rollbackOnFail) { var failingTransactionInterceptor = new FailingTransactionInterceptor(); DbInterception.Add(failingTransactionInterceptor); if (useTransactionHandler) { MutableResolver.AddResolver <Func <TransactionHandler> >( new TransactionHandlerResolver(() => new CommitFailureHandler(), null, null)); } if (useExecutionStrategy) { MutableResolver.AddResolver <Func <IDbExecutionStrategy> >( key => (Func <IDbExecutionStrategy>)(() => new SqlAzureExecutionStrategy())); } try { using (var context = new BlogContextCommit()) { FailingTransactionInterceptor.ShouldFailTimes = 0; context.Database.Delete(); Assert.Equal(1, context.Blogs.Count()); FailingTransactionInterceptor.ShouldFailTimes = 1; FailingTransactionInterceptor.ShouldRollBack = rollbackOnFail; context.Blogs.Add(new BlogContext.Blog()); runAndVerify(context); } using (var context = new BlogContextCommit()) { Assert.Equal(expectedBlogs, context.Blogs.Count()); } } finally { DbInterception.Remove(failingTransactionInterceptor); MutableResolver.ClearResolvers(); } DbDispatchersHelpers.AssertNoInterceptors(); }
private void TransactionHandler_and_ExecutionStrategy_does_not_retry_on_false_commit_fail_with_custom_implementation( Action <BlogContextCommit> runAndVerify) { var failingTransactionInterceptorMock = new Mock <FailingTransactionInterceptor> { CallBase = true }; DbInterception.Add(failingTransactionInterceptorMock.Object); MutableResolver.AddResolver <Func <TransactionHandler> >( new TransactionHandlerResolver(() => new CommitFailureHandler(), null, null)); MutableResolver.AddResolver <Func <IDbExecutionStrategy> >( key => (Func <IDbExecutionStrategy>)(() => new SqlAzureExecutionStrategy())); try { using (var context = new BlogContextCommit()) { FailingTransactionInterceptor.ShouldFailTimes = 0; context.Database.Delete(); Assert.Equal(1, context.Blogs.Count()); FailingTransactionInterceptor.ShouldFailTimes = 20; FailingTransactionInterceptor.ShouldRollBack = false; context.Blogs.Add(new BlogContext.Blog()); runAndVerify(context); FailingTransactionInterceptor.ShouldFailTimes = 0; failingTransactionInterceptorMock.Verify( m => m.Committing(It.IsAny <DbTransaction>(), It.IsAny <DbTransactionInterceptionContext>()), Times.Exactly(4)); } using (var context = new BlogContextCommit()) { Assert.Equal(2, context.Blogs.Count()); } } finally { DbInterception.Remove(failingTransactionInterceptorMock.Object); MutableResolver.ClearResolvers(); } DbDispatchersHelpers.AssertNoInterceptors(); }
private void CommitFailureHandler_with_ExecutionStrategy_test( Action <ObjectContext, Mock <SuspendableSqlAzureExecutionStrategy> > pruneAndVerify) { MutableResolver.AddResolver <Func <TransactionHandler> >( new TransactionHandlerResolver(() => new MyCommitFailureHandler(c => new TransactionContext(c)), null, null)); var executionStrategyMock = new Mock <SuspendableSqlAzureExecutionStrategy> { CallBase = true }; MutableResolver.AddResolver <Func <IDbExecutionStrategy> >( key => (Func <IDbExecutionStrategy>)(() => executionStrategyMock.Object)); try { using (var context = new BlogContextCommit()) { context.Database.Delete(); Assert.Equal(1, context.Blogs.Count()); context.Blogs.Add(new BlogContext.Blog()); context.SaveChanges(); AssertTransactionHistoryCount(context, 1); executionStrategyMock.Verify(e => e.Execute(It.IsAny <Func <int> >()), Times.Exactly(3)); #if !NET40 executionStrategyMock.Verify( e => e.ExecuteAsync(It.IsAny <Func <Task <int> > >(), It.IsAny <CancellationToken>()), Times.Never()); #endif var objectContext = ((IObjectContextAdapter)context).ObjectContext; pruneAndVerify(objectContext, executionStrategyMock); using (var transactionContext = new TransactionContext(context.Database.Connection)) { Assert.Equal(0, transactionContext.Transactions.Count()); } } } finally { MutableResolver.ClearResolvers(); } }
public void BuildDatabaseInitializationScript_can_be_used_to_initialize_the_database() { MutableResolver.AddResolver <Func <TransactionHandler> >( new TransactionHandlerResolver(() => new CommitFailureHandler(), null, null)); MutableResolver.AddResolver <Func <IDbExecutionStrategy> >( key => (Func <IDbExecutionStrategy>)(() => new SqlAzureExecutionStrategy())); try { using (var context = new BlogContextCommit()) { context.Database.Delete(); Assert.Equal(1, context.Blogs.Count()); } MutableResolver.AddResolver <Func <TransactionHandler> >( new TransactionHandlerResolver(() => new CommitFailureHandler(c => new TransactionContextNoInit(c)), null, null)); using (var context = new BlogContextCommit()) { context.Blogs.Add(new BlogContext.Blog()); Assert.Throws <EntityException>(() => context.SaveChanges()); context.Database.ExecuteSqlCommand( TransactionalBehavior.DoNotEnsureTransaction, ((IObjectContextAdapter)context).ObjectContext.TransactionHandler.BuildDatabaseInitializationScript()); context.SaveChanges(); } using (var context = new BlogContextCommit()) { Assert.Equal(2, context.Blogs.Count()); } } finally { MutableResolver.ClearResolvers(); } DbDispatchersHelpers.AssertNoInterceptors(); }
public void FromContext_returns_the_current_handler() { MutableResolver.AddResolver <Func <TransactionHandler> >( new TransactionHandlerResolver(() => new CommitFailureHandler(), null, null)); try { using (var context = new BlogContextCommit()) { context.Database.Delete(); var commitFailureHandler = CommitFailureHandler.FromContext(((IObjectContextAdapter)context).ObjectContext); Assert.IsType <CommitFailureHandler>(commitFailureHandler); Assert.Same(commitFailureHandler, CommitFailureHandler.FromContext(context)); } } finally { MutableResolver.ClearResolvers(); } }
private void Execute_commit_failure_test( Action <Action> verifyInitialization, Action <Action> verifySaveChanges, int expectedBlogs, bool useTransactionHandler, bool useExecutionStrategy, bool rollbackOnFail) { var failingTransactionInterceptorMock = new Mock <FailingTransactionInterceptor> { CallBase = true }; var failingTransactionInterceptor = failingTransactionInterceptorMock.Object; DbInterception.Add(failingTransactionInterceptor); if (useTransactionHandler) { MutableResolver.AddResolver <Func <TransactionHandler> >( new TransactionHandlerResolver(() => new CommitFailureHandler(), null, null)); } if (useExecutionStrategy) { MutableResolver.AddResolver <Func <IDbExecutionStrategy> >( key => (Func <IDbExecutionStrategy>) (() => new SqlAzureExecutionStrategy(maxRetryCount: 2, maxDelay: TimeSpan.FromMilliseconds(1)))); } try { using (var context = new BlogContextCommit()) { context.Database.Delete(); failingTransactionInterceptor.ShouldFailTimes = 1; failingTransactionInterceptor.ShouldRollBack = rollbackOnFail; verifyInitialization(() => context.Blogs.Count()); failingTransactionInterceptor.ShouldFailTimes = 0; Assert.Equal(1, context.Blogs.Count()); failingTransactionInterceptor.ShouldFailTimes = 1; context.Blogs.Add(new BlogContext.Blog()); verifySaveChanges(() => context.SaveChanges()); failingTransactionInterceptorMock.Verify( m => m.Committing(It.IsAny <DbTransaction>(), It.IsAny <DbTransactionInterceptionContext>()), Times.Exactly( useTransactionHandler ? useExecutionStrategy ? 6 : rollbackOnFail ? 4 : 3 : 4)); } using (var context = new BlogContextCommit()) { Assert.Equal(expectedBlogs, context.Blogs.Count()); using (var transactionContext = new TransactionContext(context.Database.Connection)) { using (var infoContext = GetInfoContext(transactionContext)) { Assert.True( !infoContext.TableExists("__Transactions") || !transactionContext.Transactions.Any()); } } } } finally { DbInterception.Remove(failingTransactionInterceptor); MutableResolver.ClearResolvers(); } DbDispatchersHelpers.AssertNoInterceptors(); }