PageRenderTime 60ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/Xtensive.Storage/Xtensive.Storage.Tests.Part2/Issues/Issue0631_DisconnectedStateBugs/Issue0631_DisconnectedStateBugs.cs

https://code.google.com/p/dataobjectsdotnet/
C# | 293 lines | 235 code | 36 blank | 22 comment | 19 complexity | 846baa36395042fe392a0c658ab40e27 MD5 | raw file
Possible License(s): AGPL-3.0
  1. // Copyright (C) 2003-2010 Xtensive LLC.
  2. // All rights reserved.
  3. // For conditions of distribution and use, see license.
  4. // Created by: Alex Yakunin
  5. // Created: 2010.04.12
  6. using System;
  7. using System.Linq;
  8. using System.Reflection;
  9. using NUnit.Framework;
  10. using Xtensive.Storage.Configuration;
  11. namespace Xtensive.Storage.Tests.Issues.Issue0631_DisconnectedStateBugs
  12. {
  13. [TestFixture]
  14. public class Issue0631_DisconnectedStateBugs : AutoBuildTest
  15. {
  16. private static readonly Guid guidA = new Guid("A4CB133D-257C-4FA9-B827-8915627DAAAA");
  17. private static readonly Guid guidB = new Guid("4CE5B488-33B7-48CB-A42B-B92463B0BBBB");
  18. private static readonly Guid guidC = new Guid("A1631DEC-A06F-4A48-831B-7527DEDFCCCC");
  19. private static readonly Guid guidD = new Guid("4027ECA5-5476-467B-9457-3ECD6F08DDDD");
  20. protected override DomainConfiguration BuildConfiguration()
  21. {
  22. var config = base.BuildConfiguration();
  23. config.Types.Register(Assembly.GetExecutingAssembly(), typeof (EntityBase).Namespace);
  24. return config;
  25. }
  26. protected override Domain BuildDomain(DomainConfiguration configuration)
  27. {
  28. var domain = base.BuildDomain(configuration);
  29. using (var s = Session.Open(domain)) {
  30. using (var tx = Transaction.Open()) {
  31. var e = new TestEntity(Guid.NewGuid()) {
  32. Date = DateTime.Now,
  33. Integer = 1
  34. };
  35. e.OwnedItems.Add(new OwnedEntity(guidA) { Name = "a" });
  36. e.OwnedItems.Add(new OwnedEntity(guidB) { Name = "b" });
  37. e.OwnedItems.Add(new OwnedEntity(Guid.NewGuid()));
  38. e.OwnedItems.Add(new OwnedEntity(Guid.NewGuid()));
  39. var ff = new TestEntity(Guid.NewGuid()) {
  40. Date = DateTime.Now,
  41. Integer = 2
  42. };
  43. ff.OwnedItems.Add(new OwnedEntity(Guid.NewGuid()));
  44. ff.OwnedItems.Add(new OwnedEntity(Guid.NewGuid()));
  45. ff.OwnedItems.Add(new OwnedEntity(Guid.NewGuid()));
  46. ff.OwnedItems.Add(new OwnedEntity(Guid.NewGuid()));
  47. tx.Complete();
  48. }
  49. }
  50. return domain;
  51. }
  52. [Test]
  53. public void CombinedTest()
  54. {
  55. var ds = new DisconnectedState();
  56. // Adding few items to DisconnectedState
  57. using (var session = Session.Open(Domain)) {
  58. using (ds.Attach(session)) {
  59. using (var tx = Transaction.Open()) {
  60. TestEntity doc;
  61. using (ds.Connect()) {
  62. doc = Query.All<TestEntity>().Where(f => f.Integer == 1).Single();
  63. doc.OwnedItems.Add(new OwnedEntity(guidC) { Name = "c" }); // Not a real Add
  64. doc.OwnedItems.Add(new OwnedEntity(guidD) { Name = "d" }); // Not a real Add
  65. }
  66. tx.Complete();
  67. }
  68. }
  69. }
  70. DisconnectedState dsBackup;
  71. // Removing one old and one new item
  72. using (var session = Session.Open(Domain)) {
  73. dsBackup = ds.Clone(); // Needs active Session to work properly
  74. using (ds.Attach(session)) {
  75. using (var tx = Transaction.Open()) {
  76. using (ds.Connect()) {
  77. var doc = Query.All<TestEntity>().Where(f => f.Integer == 1).Single();
  78. // Must throw an exception, since there is no real entity
  79. Assert.Throws<InvalidOperationException>(() => {
  80. doc.OwnedItems.Single(a => a.Id==guidD);
  81. });
  82. var dItem = doc.OwnedItems.ToList().Single(a => a.Id == guidD);
  83. // Must throw an exception, because OnRemoveAction on TestEntity.OwnedItems is Deny (default)
  84. Assert.Throws<ReferentialIntegrityException>(() => {
  85. dItem.Remove();
  86. });
  87. doc.OwnedItems.Remove(dItem);
  88. dItem.Remove();
  89. var aItem = Query.All<OwnedEntity>().Single(a => a.Id == guidA);
  90. doc.OwnedItems.Remove(aItem);
  91. aItem.Remove();
  92. }
  93. tx.Complete();
  94. }
  95. }
  96. }
  97. // Rolling everything back by switching back to the clone
  98. ds = dsBackup;
  99. // Modifying B and C instances and rollback the local transaction
  100. using (var session = Session.Open(Domain)) {
  101. using (ds.Attach(session)) {
  102. using (var tx = Transaction.Open()) {
  103. using (ds.Connect()) {
  104. var doc = Query.All<TestEntity>()
  105. .Where(f => f.Integer == 1)
  106. .Prefetch(s => s.OwnedItems) // Must not affect here
  107. .Single();
  108. var anotherEntities = Query.All<OwnedEntity>().ToArray();
  109. Query.Single<OwnedEntity>(guidB).Name = "b2";
  110. Query.Single<OwnedEntity>(guidC).Name = "c2";
  111. }
  112. // tx.Complete();
  113. }
  114. }
  115. }
  116. // Testing if above block has successfully completed
  117. using (var session = Session.Open(Domain)) {
  118. using (ds.Attach(session)) {
  119. using (var tx = Transaction.Open()) {
  120. using (ds.Connect()) {
  121. var doc = Query.All<TestEntity>()
  122. .Where(f => f.Integer == 1)
  123. .Prefetch(s => s.OwnedItems) // Must not affect here
  124. .Single();
  125. // Must throw an exception, since there is no real entity
  126. Assert.Throws<InvalidOperationException>(() => {
  127. Query.All<OwnedEntity>().Single(a => a.Id==guidC);
  128. });
  129. // But it esxists in EntitySet
  130. Assert.AreEqual(Query.Single<OwnedEntity>(guidB).Name, "b");
  131. // And this one is in database
  132. Assert.AreEqual(Query.All<OwnedEntity>().Single(a => a.Id == guidB).Name, "b");
  133. }
  134. }
  135. }
  136. }
  137. // Really modifying B and C instances
  138. using (var session = Session.Open(Domain)) {
  139. using (ds.Attach(session)) {
  140. using (var tx = Transaction.Open()) {
  141. using (ds.Connect()) {
  142. var doc = Query.All<TestEntity>()
  143. .Where(f => f.Integer == 1)
  144. .Prefetch(s => s.OwnedItems) // Must not affect here
  145. .Single();
  146. Query.Single<OwnedEntity>(guidB).Name = "b2";
  147. Query.Single<OwnedEntity>(guidC).Name = "c2";
  148. var aItem = Query.All<OwnedEntity>().Single(a => a.Id == guidA);
  149. doc.OwnedItems.Remove(aItem);
  150. aItem.Remove();
  151. }
  152. tx.Complete();
  153. }
  154. }
  155. }
  156. // Testing if above block has successfully completed
  157. using (var session = Session.Open(Domain)) {
  158. using (ds.Attach(session)) {
  159. using (var tx = Transaction.Open()) {
  160. using (ds.Connect()) {
  161. var doc = Query.All<TestEntity>()
  162. .Where(f => f.Integer == 1)
  163. .Prefetch(s => s.OwnedItems) // Must not affect here
  164. .Single();
  165. Assert.AreEqual(Query.Single<OwnedEntity>(guidC).Name, "c2");
  166. Assert.AreEqual(Query.Single<OwnedEntity>(guidB).Name, "b2");
  167. Assert.IsNull(Query.SingleOrDefault<OwnedEntity>(guidA));
  168. var ownedItems = doc.OwnedItems.ToList();
  169. Assert.IsFalse(ownedItems.Any(i => i.Id == guidA));
  170. }
  171. }
  172. }
  173. }
  174. // Applying all the changes
  175. using (var session = Session.Open(Domain)) {
  176. ds.ApplyChanges(session);
  177. }
  178. // Testing if above block has successfully completed
  179. using (var session = Session.Open(Domain)) {
  180. using (var tx = Transaction.Open()) {
  181. Assert.AreEqual(Query.All<OwnedEntity>().Single(i => i.Id == guidB).Name, "b2");
  182. Assert.AreEqual(Query.All<OwnedEntity>().Single(i => i.Id == guidC).Name, "c2");
  183. Assert.AreEqual(Query.All<OwnedEntity>().Single(i => i.Id == guidD).Name, "d");
  184. Assert.IsNull(Query.All<OwnedEntity>().SingleOrDefault(i => i.Id == guidA));
  185. var doc = Query.All<TestEntity>()
  186. .Where(f => f.Integer == 1)
  187. .Prefetch(s => s.OwnedItems) // Must not affect here
  188. .Single();
  189. Assert.IsFalse(doc.OwnedItems.Any(i => i.Id == guidA));
  190. }
  191. }
  192. }
  193. [Test]
  194. public void PartialSelectTest()
  195. {
  196. var state = new DisconnectedState();
  197. using (var session = Session.Open(Domain)) {
  198. using (state.Attach(session)) {
  199. using (var tx = Transaction.Open()) {
  200. using (state.Connect()) {
  201. var partialResult = Query.All<TestEntity>().Select(u => new { u.Date }).ToList();
  202. // Exception here, to be fixed
  203. var fullResult = Query.All<TestEntity>().ToList();
  204. }
  205. tx.Complete();
  206. }
  207. }
  208. }
  209. }
  210. [Test]
  211. public void SameEntitySelect()
  212. {
  213. var state = new DisconnectedState();
  214. using (var session = Session.Open(Domain)) {
  215. using (state.Attach(session)) {
  216. using (var tx = Transaction.Open()) {
  217. using (state.Connect()) {
  218. var doc = Query.All<TestEntity>()
  219. .Where(f => f.Integer == 1)
  220. .Prefetch(s => s.OwnedItems)
  221. .Single();
  222. var subs = doc.OwnedItems.Where(g => true).ToList();
  223. foreach (var sub in subs) {
  224. sub.Name = "1111";
  225. }
  226. doc.OwnedItems.Add(new OwnedEntity(Guid.NewGuid()));
  227. doc.OwnedItems.Add(new OwnedEntity(Guid.NewGuid()));
  228. doc.OwnedItems.Add(new OwnedEntity(Guid.NewGuid()));
  229. }
  230. var fe = new TestEntity(Guid.NewGuid()) { Date = DateTime.Now, Integer = 123 };
  231. fe.Integer = 2222;
  232. tx.Complete();
  233. }
  234. }
  235. }
  236. using (var session = Session.Open(Domain)) {
  237. using (state.Attach(session)) {
  238. using (var tx = Transaction.Open()) {
  239. using (state.Connect()) {
  240. // Exception here
  241. var doc = Query.All<TestEntity>()
  242. .Where(f => f.Integer == 1)
  243. .Prefetch(s => s.OwnedItems)
  244. .Single();
  245. var subs = doc.OwnedItems.Where(g => true).ToList();
  246. foreach (var sub in subs) {
  247. sub.Name = "22222";
  248. }
  249. }
  250. tx.Complete();
  251. }
  252. state.ApplyChanges();
  253. }
  254. }
  255. }
  256. }
  257. }