示例#1
0
        public void BeforeCloseAfterCloseCanceled()
        {
            var id1 = Guid.NewGuid();
            var log = new List <string>();

            using (var scope = RhetosProcessHelper.CreateScope())
            {
                var transaction = scope.Resolve <IPersistenceTransaction>();
                transaction.BeforeClose += () => log.Add("before");
                transaction.AfterClose  += () => log.Add("after");

                var repository = scope.Resolve <Common.DomRepository>();
                repository.TestEntity.BaseEntity.Insert(new TestEntity.BaseEntity {
                    ID = id1, Name = TestNamePrefix + Guid.NewGuid()
                });
            }

            Assert.AreEqual("", TestUtility.Dump(log));

            using (var scope = RhetosProcessHelper.CreateScope())
            {
                var context = scope.Resolve <Common.ExecutionContext>();
                Assert.IsFalse(context.Repository.TestEntity.BaseEntity.Query(new[] { id1 }).Any());
            }
        }
示例#2
0
        public void RollbackByDefault()
        {
            var id1 = Guid.NewGuid();

            TestUtility.ShouldFail <FrameworkException>(() =>
            {
                using (var scope = RhetosProcessHelper.ProcessContainer.CreateTransactionScopeContainer())
                {
                    var context = scope.Resolve <Common.ExecutionContext>();
                    context.Repository.TestEntity.BaseEntity.Insert(new TestEntity.BaseEntity {
                        ID = id1, Name = TestNamePrefix + Guid.NewGuid()
                    });
                    throw new FrameworkException(nameof(RollbackByDefault)); // The exception that is not handled within transaction scope.
#pragma warning disable CS0162                                               // Unreachable code detected
                    scope.CommitChanges();
#pragma warning restore CS0162                                               // Unreachable code detected
                }
            },
                                                        nameof(RollbackByDefault));

            using (var scope = RhetosProcessHelper.CreateScope())
            {
                var context = scope.Resolve <Common.ExecutionContext>();
                Assert.IsFalse(context.Repository.TestEntity.BaseEntity.Query(new[] { id1 }).Any());
            }
        }
示例#3
0
        public void IndependentTransactions()
        {
            const int threadCount = 2;

            int initialCount;

            using (var scope = RhetosProcessHelper.CreateScope())
            {
                RhetosProcessHelper.CheckForParallelism(scope.Resolve <ISqlExecuter>(), threadCount);

                var context = scope.Resolve <Common.ExecutionContext>();
                initialCount = context.Repository.TestEntity.BaseEntity.Query().Count();
            }

            var id1 = Guid.NewGuid();

            Parallel.For(0, threadCount, thread =>
            {
                using (var scope = RhetosProcessHelper.CreateScope())
                {
                    var context = scope.Resolve <Common.ExecutionContext>();

                    Assert.AreEqual(initialCount, context.Repository.TestEntity.BaseEntity.Query().Count());
                    Thread.Sleep(100);
                    context.Repository.TestEntity.BaseEntity.Insert(new TestEntity.BaseEntity {
                        ID = id1, Name = TestNamePrefix + Guid.NewGuid()
                    });                                                                                                                              // Each thread uses the same ID to make sure only one thread can run this code at same time.
                    Assert.AreEqual(initialCount + 1, context.Repository.TestEntity.BaseEntity.Query().Count());
                }
            });
        }
示例#4
0
        public void CommitAndCloseWithDiscard()
        {
            var id1 = Guid.NewGuid();
            var id2 = Guid.NewGuid();

            TestUtility.ShouldFail <FrameworkException>(() =>
            {
                using (var scope = RhetosProcessHelper.CreateScope())
                {
                    var context = scope.Resolve <Common.ExecutionContext>();
                    context.Repository.TestEntity.BaseEntity.Insert(new TestEntity.BaseEntity {
                        ID = id1, Name = TestNamePrefix + Guid.NewGuid()
                    });
                    scope.Resolve <IPersistenceTransaction>().DiscardChanges();
                    scope.CommitAndClose();
                    context.Repository.TestEntity.BaseEntity.Insert(new TestEntity.BaseEntity {
                        ID = id2, Name = TestNamePrefix + Guid.NewGuid()
                    });
                }
            },
                                                        "disposed persistence transaction"); // CommitAndClose should close the transaction, even if it was discarded.

            using (var scope = RhetosProcessHelper.CreateScope())
            {
                var context = scope.Resolve <Common.ExecutionContext>();
                // CommitAndClose should rollback the transaction.
                var ids = new[] { id1, id2 };
                Assert.AreEqual(
                    "",
                    TestUtility.DumpSorted(context.Repository.TestEntity.BaseEntity.Load(ids), item => item.ID));
            }
        }
示例#5
0
        public void EarlyCommitAndClose()
        {
            var id1 = Guid.NewGuid();
            var id2 = Guid.NewGuid();

            TestUtility.ShouldFail <FrameworkException>(() =>
            {
                using (var scope = RhetosProcessHelper.CreateScope())
                {
                    var context = scope.Resolve <Common.ExecutionContext>();
                    context.Repository.TestEntity.BaseEntity.Insert(new TestEntity.BaseEntity {
                        ID = id1, Name = TestNamePrefix + Guid.NewGuid()
                    });
                    scope.CommitAndClose();     // CommitAndClose is incorrectly placed at this position.
                    context.Repository.TestEntity.BaseEntity.Insert(new TestEntity.BaseEntity {
                        ID = id2, Name = TestNamePrefix + Guid.NewGuid()
                    });
                }
            },
                                                        "disposed persistence transaction");

            using (var scope = RhetosProcessHelper.CreateScope())
            {
                var context = scope.Resolve <Common.ExecutionContext>();
                // Only operations before CommitAndClose are committed.
                var ids = new[] { id1, id2 };
                Assert.AreEqual(
                    id1.ToString(),
                    TestUtility.DumpSorted(context.Repository.TestEntity.BaseEntity.Load(ids), item => item.ID));
            }
        }
示例#6
0
        public void EarlyCommitOnDispose()
        {
            var id1 = Guid.NewGuid();
            var id2 = Guid.NewGuid();

            TestUtility.ShouldFail <FrameworkException>(() =>
            {
                using (var scope = RhetosProcessHelper.ProcessContainer.CreateTransactionScopeContainer())
                {
                    var context = scope.Resolve <Common.ExecutionContext>();
                    context.Repository.TestEntity.BaseEntity.Insert(new TestEntity.BaseEntity {
                        ID = id1, Name = TestNamePrefix + Guid.NewGuid()
                    });
                    scope.CommitChanges();     // CommitChanges is incorrectly placed at this position.
                    context.Repository.TestEntity.BaseEntity.Insert(new TestEntity.BaseEntity {
                        ID = id2, Name = TestNamePrefix + Guid.NewGuid()
                    });
                    throw new FrameworkException(nameof(EarlyCommitOnDispose));     // The exception is not handled within transaction scope to discard the transaction.
                }
            },
                                                        nameof(EarlyCommitOnDispose));

            using (var scope = RhetosProcessHelper.CreateScope())
            {
                var context = scope.Resolve <Common.ExecutionContext>();
                // The transaction is committed because of incorrect implementation pattern above.
                var ids = new[] { id1, id2 };
                Assert.AreEqual(
                    TestUtility.DumpSorted(ids),
                    TestUtility.DumpSorted(context.Repository.TestEntity.BaseEntity.Load(ids), item => item.ID));
            }
        }
示例#7
0
 public static void ClassCleanup()
 {
     using (var scope = RhetosProcessHelper.CreateScope())
     {
         var context   = scope.Resolve <Common.ExecutionContext>();
         var testItems = context.Repository.TestEntity.BaseEntity.Load(item => item.Name.StartsWith(TestNamePrefix));
         context.Repository.TestEntity.BaseEntity.Delete(testItems);
         scope.CommitAndClose();
     }
 }
示例#8
0
        public void FailedCleanupRollback()
        {
            var    id1       = Guid.NewGuid();
            var    log       = new List <string>();
            var    systemLog = new List <string>();
            string testName  = TestNamePrefix + Guid.NewGuid();

            using (var scope = RhetosProcessHelper.CreateScope(builder =>
                                                               builder.AddLogMonitor(systemLog, EventType.Trace)))
            {
                var transaction = scope.Resolve <IPersistenceTransaction>();
                transaction.BeforeClose += () => log.Add("before1");
                transaction.BeforeClose += () => throw new InvalidOperationException(testName + "-before");
                transaction.BeforeClose += () => log.Add("before2");
                transaction.AfterClose  += () => log.Add("after");

                var repository = scope.Resolve <Common.DomRepository>();
                repository.TestEntity.BaseEntity.Insert(new TestEntity.BaseEntity {
                    ID = id1, Name = testName
                });

                var dbTransaction = (DbTransaction)transaction.GetType().GetField("_transaction", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(transaction);
                dbTransaction.Rollback(); // This will cause error on commit or rollback, when IPersistenceTransaction is Disposed.

                systemLog.Clear();
                TestUtility.ShouldFail <InvalidOperationException>(
                    () => scope.CommitAndClose(),
                    testName + "-before");

                TestUtility.AssertContains(
                    string.Join(Environment.NewLine, systemLog),
                    new[] { "Rolling back transaction", "Closing connection" });

                TestUtility.ShouldFail <FrameworkException>(
                    () => Assert.IsNull(transaction.Connection),
                    "Trying to use the Connection property of a disposed persistence transaction.");
            }

            Assert.AreEqual("before1", TestUtility.Dump(log));
            // Failure on rollback should not throw an exception, to allow other cleanup code to be executed. Also, a previously handled database connection error may have triggered the rollback.
            using (var scope = RhetosProcessHelper.CreateScope())
            {
                var context = scope.Resolve <Common.ExecutionContext>();
                Assert.IsFalse(context.Repository.TestEntity.BaseEntity.Query(new[] { id1 }).Any());
            }
        }
示例#9
0
        public void FailedCommit()
        {
            var    id1       = Guid.NewGuid();
            var    log       = new List <string>();
            var    systemLog = new List <string>();
            string testName  = TestNamePrefix + Guid.NewGuid();

            using (var scope = RhetosProcessHelper.CreateScope(builder =>
                                                               builder.AddLogMonitor(systemLog, EventType.Trace)))
            {
                var transaction = scope.Resolve <IPersistenceTransaction>();
                transaction.BeforeClose += () => log.Add("before");
                transaction.AfterClose  += () => log.Add("after");

                var repository = scope.Resolve <Common.DomRepository>();
                repository.TestEntity.BaseEntity.Insert(new TestEntity.BaseEntity {
                    ID = id1, Name = testName
                });

                var dbTransaction = (DbTransaction)transaction.GetType().GetField("_transaction", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(transaction);
                dbTransaction.Rollback(); // This will cause error on commit or rollback, when IPersistenceTransaction is Disposed.

                systemLog.Clear();

                TestUtility.ShouldFail(
                    () => scope.CommitAndClose(),
                    "This SqlTransaction has completed; it is no longer usable.");

                TestUtility.AssertContains(
                    string.Join(Environment.NewLine, systemLog),
                    new[] { "Closing connection" });

                TestUtility.ShouldFail <FrameworkException>(
                    () => Assert.IsNull(transaction.Connection),
                    "Trying to use the Connection property of a disposed persistence transaction.");
            }

            Assert.AreEqual("before", TestUtility.Dump(log));

            using (var scope = RhetosProcessHelper.CreateScope())
            {
                var context = scope.Resolve <Common.ExecutionContext>();
                Assert.IsFalse(context.Repository.TestEntity.BaseEntity.Query(new[] { id1 }).Any());
            }
        }
示例#10
0
        public void ExplicitCommitAndClose()
        {
            var id1 = Guid.NewGuid();

            using (var scope = RhetosProcessHelper.CreateScope())
            {
                var context = scope.Resolve <Common.ExecutionContext>();
                context.Repository.TestEntity.BaseEntity.Insert(new TestEntity.BaseEntity {
                    ID = id1, Name = TestNamePrefix + Guid.NewGuid()
                });
                scope.CommitAndClose();
            }

            using (var scope = RhetosProcessHelper.CreateScope())
            {
                var context = scope.Resolve <Common.ExecutionContext>();
                Assert.IsTrue(context.Repository.TestEntity.BaseEntity.Query(new[] { id1 }).Any());
            }
        }
示例#11
0
        public void BeforeCloseFailed()
        {
            var    id1       = Guid.NewGuid();
            var    log       = new List <string>();
            var    systemLog = new List <string>();
            string testName  = TestNamePrefix + Guid.NewGuid();

            using (var scope = RhetosProcessHelper.CreateScope(builder =>
                                                               builder.AddLogMonitor(systemLog, EventType.Trace)))
            {
                var transaction = scope.Resolve <IPersistenceTransaction>();
                transaction.BeforeClose += () => log.Add("before1");
                transaction.BeforeClose += () => throw new InvalidOperationException(testName);
                transaction.BeforeClose += () => log.Add("before2");
                transaction.AfterClose  += () => log.Add("after");

                var repository = scope.Resolve <Common.DomRepository>();
                repository.TestEntity.BaseEntity.Insert(new TestEntity.BaseEntity {
                    ID = id1, Name = testName
                });

                TestUtility.ShouldFail <InvalidOperationException>(
                    () => scope.CommitAndClose(),
                    testName);

                TestUtility.AssertContains(
                    string.Join(Environment.NewLine, systemLog),
                    new[] { "Rolling back transaction", "Closing connection" });

                TestUtility.ShouldFail <FrameworkException>(
                    () => Assert.IsNull(transaction.Connection),
                    "Trying to use the Connection property of a disposed persistence transaction.");
            }

            Assert.AreEqual("before1", TestUtility.Dump(log));

            using (var scope = RhetosProcessHelper.CreateScope())
            {
                var context = scope.Resolve <Common.ExecutionContext>();
                Assert.IsFalse(context.Repository.TestEntity.BaseEntity.Query(new[] { id1 }).Any());
            }
        }