Exemplo n.º 1
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));
            }
        }
Exemplo n.º 2
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());
            }
        }
Exemplo n.º 3
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());
            }
        }
Exemplo n.º 4
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());
                }
            });
        }
Exemplo n.º 5
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));
            }
        }
Exemplo n.º 6
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));
            }
        }
Exemplo n.º 7
0
        private Exception[] ExecuteParallel(Action <Common.ExecutionContext>[] actions, Action <Common.ExecutionContext> coldStartInsert, Action <Common.ExecutionContext> coldStartQuery)
        {
            int threadCount = actions.Count();

            using (var container = new RhetosTestContainer(true))
            {
                var sqlExecuter = container.Resolve <ISqlExecuter>();
                RhetosProcessHelper.CheckForParallelism(sqlExecuter, threadCount);
                DeleteOldData(container);

                coldStartInsert(container.Resolve <Common.ExecutionContext>());
            }

            var containers = Enumerable.Range(0, threadCount).Select(t => new RhetosTestContainer(true)).ToArray();

            var exceptions = new Exception[threadCount];

            try
            {
                var contexts = containers.Select(c => c.Resolve <Common.ExecutionContext>()).ToArray();
                foreach (var context in contexts)
                {
                    coldStartQuery(context);
                }

                Parallel.For(0, threadCount, thread =>
                {
                    try
                    {
                        actions[thread].Invoke(contexts[thread]);
                    }
                    catch (Exception ex)
                    {
                        exceptions[thread] = ex;
                        contexts[thread].PersistenceTransaction.DiscardChanges();
                    }
                    finally
                    {
                        containers[thread].Dispose();
                        containers[thread] = null;
                    }
                });
            }
            finally
            {
                foreach (var c in containers)
                {
                    if (c != null)
                    {
                        c.Dispose();
                    }
                }
            }

            for (int x = 0; x < threadCount; x++)
            {
                Console.WriteLine("Exception " + x + ": " + exceptions[x] + ".");
            }
            return(exceptions);
        }
Exemplo n.º 8
0
        public void EarlyCommit()
        {
            var id1 = Guid.NewGuid();

            try
            {
                using (var container = RhetosProcessHelper.CreateTransactionScopeContainer())
                {
                    container.CommitChanges(); // CommitChanges is incorrectly places at this position.
                    var context = container.Resolve <Common.ExecutionContext>();
                    context.Repository.TestEntity.BaseEntity.Insert(new TestEntity.BaseEntity {
                        ID = id1
                    });
                    throw new FrameworkException(nameof(EarlyCommit)); // The exception is not handled within transaction scope to discard the transaction.
                }
            }
            catch (FrameworkException ex)
            {
                Console.WriteLine($"{ex.GetType().Name}: {ex.Message}");
            }

            using (var container = RhetosProcessHelper.CreateTransactionScopeContainer())
            {
                var context = container.Resolve <Common.ExecutionContext>();
                Assert.IsTrue(context.Repository.TestEntity.BaseEntity.Query(new[] { id1 }).Any()); // The transaction is committed because of incorrect implementation pattern above.
            }
        }
Exemplo n.º 9
0
        public void RollbackByDefault()
        {
            var id1 = Guid.NewGuid();

            try
            {
                using (var container = RhetosProcessHelper.CreateTransactionScopeContainer())
                {
                    var context = container.Resolve <Common.ExecutionContext>();
                    context.Repository.TestEntity.BaseEntity.Insert(new TestEntity.BaseEntity {
                        ID = id1
                    });
                    throw new FrameworkException(nameof(RollbackByDefault)); // The exception that is not handled within transaction scope.
#pragma warning disable CS0162                                               // Unreachable code detected
                    container.CommitChanges();
#pragma warning restore CS0162                                               // Unreachable code detected
                }
            }
            catch (FrameworkException ex)
            {
                Console.WriteLine($"{ex.GetType().Name}: {ex.Message}");
            }

            using (var container = RhetosProcessHelper.CreateTransactionScopeContainer())
            {
                var context = container.Resolve <Common.ExecutionContext>();
                Assert.IsFalse(context.Repository.TestEntity.BaseEntity.Query(new[] { id1 }).Any());
            }
        }
Exemplo n.º 10
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();
     }
 }
Exemplo n.º 11
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());
            }
        }
Exemplo n.º 12
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());
            }
        }
Exemplo n.º 13
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());
            }
        }
Exemplo n.º 14
0
        public void ExplicitCommit()
        {
            var id1 = Guid.NewGuid();

            using (var container = RhetosProcessHelper.CreateTransactionScopeContainer())
            {
                var context = container.Resolve <Common.ExecutionContext>();
                context.Repository.TestEntity.BaseEntity.Insert(new TestEntity.BaseEntity {
                    ID = id1
                });
                container.CommitChanges();
            }

            using (var container = RhetosProcessHelper.CreateTransactionScopeContainer())
            {
                var context = container.Resolve <Common.ExecutionContext>();
                Assert.IsTrue(context.Repository.TestEntity.BaseEntity.Query(new[] { id1 }).Any());
            }
        }
Exemplo n.º 15
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());
            }
        }
Exemplo n.º 16
0
        private void Execute2ParallelInserts(int testCount, Action <int, TestAutoCodeCached._Helper.Simple_Repository> action)
        {
            const int threadCount = 2;

            using (var container = new RhetosTestContainer(true))
            {
                DeleteOldData(container);
                RhetosProcessHelper.CheckForParallelism(container.Resolve <ISqlExecuter>(), threadCount);
            }

            for (int test = 1; test <= testCount; test++)
            {
                Console.WriteLine("Test: " + test);

                var containers   = new[] { new RhetosTestContainer(true), new RhetosTestContainer(true) };
                var repositories = containers.Select(c => c.Resolve <Common.DomRepository>().TestAutoCodeCached.Simple).ToList();
                foreach (var r in repositories)
                {
                    Assert.IsTrue(r.Query().Count() >= 0); // Cold start.
                }
                try
                {
                    Parallel.For(0, threadCount, process =>
                    {
                        action(process, repositories[process]);
                        containers[process].Dispose();
                        containers[process] = null;
                    });
                }
                finally
                {
                    foreach (var c in containers)
                    {
                        if (c != null)
                        {
                            c.Dispose();
                        }
                    }
                }
            }
        }