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"); } }
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"); } }