public void ParentLocked()
        {
            using (var container = new RhetosTestContainer())
            {
                var repository = container.Resolve <Common.DomRepository>();

                var parentId0 = Guid.NewGuid();
                var parentId1 = Guid.NewGuid();
                var id0       = Guid.NewGuid();
                var id1       = Guid.NewGuid();
                container.Resolve <ISqlExecuter>().ExecuteSql(new[]
                {
                    "DELETE FROM TestPessimisticLocking.Article;",
                    "DELETE FROM TestPessimisticLocking.ArticleGroup;",
                    "DELETE FROM Common.ExclusiveLock;",
                    "INSERT INTO TestPessimisticLocking.ArticleGroup (ID, Name) SELECT '" + parentId0 + "', 'group1';",
                    "INSERT INTO TestPessimisticLocking.ArticleGroup (ID, Name) SELECT '" + parentId1 + "', 'group2';",
                    "INSERT INTO TestPessimisticLocking.Article (ID, Name, ParentID) SELECT '" + id0 + "', 'aaa', '" + parentId0 + "';",
                    "INSERT INTO TestPessimisticLocking.Article (ID, Name, ParentID) SELECT '" + id1 + "', 'bbb', '" + parentId1 + "';"
                });

                var articleRepos = repository.TestPessimisticLocking.Article;
                var lockRepos    = repository.Common.ExclusiveLock;

                var groups   = repository.TestPessimisticLocking.ArticleGroup.All().OrderBy(item => item.Name).ToArray();
                var articles = articleRepos.All().OrderBy(item => item.Name).ToArray();
                foreach (var article in articles)
                {
                    container.Resolve <Common.ExecutionContext>().EntityFrameworkContext.ClearCache(article);
                }

                foreach (var article in articles)
                {
                    article.Name = article.Name + "1";
                }
                articleRepos.Update(articles);
                Assert.AreEqual("aaa1, bbb1", TestUtility.DumpSorted(articleRepos.All(), item => item.Name), "updated without locks");

                // Update detail with locked parent:

                foreach (var article in articles)
                {
                    article.Name = article.Name + "2";
                }
                var myLock = new Common.ExclusiveLock
                {
                    UserName     = "******",
                    Workstation  = container.Resolve <IUserInfo>().Workstation,
                    ResourceType = "TestPessimisticLocking.ArticleGroup",
                    ResourceID   = parentId0,
                    LockStart    = DateTime.Now,
                    LockFinish   = DateTime.Now.AddSeconds(10)
                };
                lockRepos.Insert(new[] { myLock });
                TestUtility.ShouldFail(() => articleRepos.Update(articles), parentId0.ToString(), "OtherUser");

                myLock.UserName    = container.Resolve <IUserInfo>().UserName;
                myLock.Workstation = "OtherWorkstation";
                lockRepos.Update(new[] { myLock });
                TestUtility.ShouldFail(() => articleRepos.Update(articles), parentId0.ToString(), "OtherWorkstation");

                myLock.UserName    = container.Resolve <IUserInfo>().UserName;
                myLock.Workstation = container.Resolve <IUserInfo>().Workstation;
                lockRepos.Update(new[] { myLock });
                articleRepos.Update(articles);
                Assert.AreEqual("aaa12, bbb12", TestUtility.DumpSorted(articleRepos.All(), item => item.Name), "updated with OWNED parent lock");

                // Remove detail from locked parent (by deleting or updating Parent reference):

                myLock.UserName = "******";
                lockRepos.Update(new[] { myLock });
                articles[0].ParentID = groups[1].ID;

                Assert.IsTrue(articles.All(item => item.ParentID != myLock.ResourceID), "New values do not contain locked parents, but old values do");
                TestUtility.ShouldFail(() => articleRepos.Update(articles), parentId0.ToString(), "OtherUser");

                TestUtility.ShouldFail(() => articleRepos.Delete(new[] { articles[0] }), parentId0.ToString(), "OtherUser");

                myLock.UserName = container.Resolve <IUserInfo>().UserName;
                lockRepos.Update(new[] { myLock });
                articleRepos.Update(articles);
                Assert.AreEqual("aaa12, bbb12", TestUtility.DumpSorted(articleRepos.All(), item => item.Name), "Updated with OWNED old parent lock");

                // Insert new detail into locked parent:

                myLock.UserName = "******";
                lockRepos.Update(new[] { myLock });
                var newArticle = new TestPessimisticLocking.Article {
                    ID = Guid.NewGuid(), Name = "ccc", ParentID = groups[0].ID
                };
                TestUtility.ShouldFail(() => articleRepos.Insert(new[] { newArticle }), parentId0.ToString(), "OtherUser");

                myLock.UserName = container.Resolve <IUserInfo>().UserName;
                lockRepos.Update(new[] { myLock });
                articleRepos.Insert(new[] { newArticle });
                Assert.AreEqual("aaa12, bbb12, ccc", TestUtility.DumpSorted(articleRepos.All(), item => item.Name), "Inserted with OWNED new parent lock");
            }
        }
Example #2
0
        public void ParentLocked()
        {
            using (var executionContext = new CommonTestExecutionContext())
            {
                var repository = new Common.DomRepository(executionContext);

                var parentId0 = Guid.NewGuid();
                var parentId1 = Guid.NewGuid();
                var id0 = Guid.NewGuid();
                var id1 = Guid.NewGuid();
                executionContext.SqlExecuter.ExecuteSql(new[]
                    {
                        "DELETE FROM TestPessimisticLocking.Article;",
                        "DELETE FROM TestPessimisticLocking.ArticleGroup;",
                        "DELETE FROM Common.ExclusiveLock;",
                        "INSERT INTO TestPessimisticLocking.ArticleGroup (ID, Name) SELECT '" + parentId0 + "', 'group1';",
                        "INSERT INTO TestPessimisticLocking.ArticleGroup (ID, Name) SELECT '" + parentId1 + "', 'group2';",
                        "INSERT INTO TestPessimisticLocking.Article (ID, Name, ParentID) SELECT '" + id0 + "', 'aaa', '" + parentId0 + "';",
                        "INSERT INTO TestPessimisticLocking.Article (ID, Name, ParentID) SELECT '" + id1 + "', 'bbb', '" + parentId1 + "';"
                    });

                var articleRepos = repository.TestPessimisticLocking.Article;
                var lockRepos = repository.Common.ExclusiveLock;

                var groups = repository.TestPessimisticLocking.ArticleGroup.All().OrderBy(item => item.Name).ToArray();
                var articles = articleRepos.All().OrderBy(item => item.Name).ToArray();
                foreach (var article in articles)
                    executionContext.NHibernateSession.Evict(article);

                foreach (var article in articles)
                    article.Name = article.Name + "1";
                articleRepos.Update(articles);
                Assert.AreEqual("aaa1, bbb1", TestUtility.DumpSorted(articleRepos.All(), item => item.Name), "updated without locks");

                // Update detail with locked parent:

                foreach (var article in articles)
                    article.Name = article.Name + "2";
                var myLock = new Common.ExclusiveLock
                {
                    UserName = "******",
                    Workstation = executionContext.UserInfo.Workstation,
                    ResourceType = "TestPessimisticLocking.ArticleGroup",
                    ResourceID = parentId0,
                    LockStart = DateTime.Now,
                    LockFinish = DateTime.Now.AddSeconds(10)
                };
                lockRepos.Insert(new[] { myLock });
                TestUtility.ShouldFail(() => articleRepos.Update(articles), parentId0.ToString(), "OtherUser");

                myLock.UserName = executionContext.UserInfo.UserName;
                myLock.Workstation = "OtherWorkstation";
                lockRepos.Update(new[] { myLock });
                TestUtility.ShouldFail(() => articleRepos.Update(articles), parentId0.ToString(), "OtherWorkstation");

                myLock.UserName = executionContext.UserInfo.UserName;
                myLock.Workstation = executionContext.UserInfo.Workstation;
                lockRepos.Update(new[] { myLock });
                articleRepos.Update(articles);
                Assert.AreEqual("aaa12, bbb12", TestUtility.DumpSorted(articleRepos.All(), item => item.Name), "updated with OWNED parent lock");

                // Remove detail from locked parent (by deleting or updating Parent reference):

                myLock.UserName = "******";
                lockRepos.Update(new[] { myLock });
                articles[0].Parent = groups[1];

                Assert.IsTrue(articles.All(item => item.Parent.ID != myLock.ResourceID), "New values do not contain locked parents, but old values do");
                TestUtility.ShouldFail(() => articleRepos.Update(articles), parentId0.ToString(), "OtherUser");

                TestUtility.ShouldFail(() => articleRepos.Delete(new[] { articles[0] }), parentId0.ToString(), "OtherUser");

                myLock.UserName = executionContext.UserInfo.UserName;
                lockRepos.Update(new[] { myLock });
                articleRepos.Update(articles);
                Assert.AreEqual("aaa12, bbb12", TestUtility.DumpSorted(articleRepos.All(), item => item.Name), "Updated with OWNED old parent lock");

                // Insert new detail into locked parent:

                myLock.UserName = "******";
                lockRepos.Update(new[] { myLock });
                var newArticle = new TestPessimisticLocking.Article { ID = Guid.NewGuid(), Name = "ccc", Parent = groups[0] };
                TestUtility.ShouldFail(() => articleRepos.Insert(new[] { newArticle }), parentId0.ToString(), "OtherUser");

                myLock.UserName = executionContext.UserInfo.UserName;
                lockRepos.Update(new[] { myLock });
                articleRepos.Insert(new[] { newArticle });
                Assert.AreEqual("aaa12, bbb12, ccc", TestUtility.DumpSorted(articleRepos.All(), item => item.Name), "Inserted with OWNED new parent lock");
            }
        }