示例#1
0
        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);
        }
示例#2
0
        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();
        }
示例#3
0
        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();
        }
示例#4
0
        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);
        }
示例#5
0
        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();
        }
示例#6
0
        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();
        }
示例#7
0
        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();
        }
示例#8
0
        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();
            }
        }
示例#9
0
        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();
        }
示例#10
0
        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();
            }
        }
示例#11
0
        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();
        }