Skip to content

Commit 2f04c22

Browse files
committed
EntitySet.Count returns correct value in Client profile
EntitySetState.TotalItemCount used to be overwritten when prefetch even if there were some local changes. That caused EntitySet.Count returning count of only persisted items during Client profile sessions.
1 parent e3972b6 commit 2f04c22

2 files changed

Lines changed: 166 additions & 12 deletions

File tree

Orm/Xtensive.Orm.Tests/Storage/NewProfilesTest.cs

Lines changed: 134 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2014 Xtensive LLC.
1+
// Copyright (C) 2014 Xtensive LLC.
22
// All rights reserved.
33
// For conditions of distribution and use, see license.
44
// Created by: Alexey Kulakov
@@ -986,5 +986,138 @@ public void ClientProfileRollbackEntitySetsWhenPersistHasFallen()
986986
Assert.AreEqual(0, session.Query.All<Author>().First(author => author.Name=="Mathew").Books.Count);
987987
}
988988
}
989+
990+
[Test]
991+
public void ClientProfileEntitySetCountTest01()
992+
{
993+
long bookId = 0;
994+
using (var session = Domain.OpenSession(serverProfile))
995+
using (var transactionScope = session.OpenTransaction()) {
996+
var book = new Book() { Title = "First book" };
997+
998+
var comment1 = new Comment();
999+
var comment2 = new Comment();
1000+
1001+
book.Comments.Add(comment1);
1002+
book.Comments.Add(comment2);
1003+
1004+
bookId = book.Id;
1005+
transactionScope.Complete();
1006+
}
1007+
1008+
using (var session = Domain.OpenSession(clientProfile)) {
1009+
var book = session.Query.All<Book>().FirstOrDefault(b => b.Id == bookId);
1010+
1011+
var dummyCount = book.Comments.Count;
1012+
book.Comments.Add(new Comment());
1013+
1014+
Assert.That(book.Comments.Count, Is.EqualTo(3));
1015+
}
1016+
}
1017+
1018+
[Test]
1019+
public void ClientProfileEntitySetCount02()
1020+
{
1021+
long bookId = 0;
1022+
using (var session = Domain.OpenSession(serverProfile))
1023+
using (var transactionScope = session.OpenTransaction()) {
1024+
var book = new Book() { Title = "First book" };
1025+
1026+
var comment1 = new Comment();
1027+
var comment2 = new Comment();
1028+
1029+
book.Comments.Add(comment1);
1030+
book.Comments.Add(comment2);
1031+
1032+
bookId = book.Id;
1033+
transactionScope.Complete();
1034+
}
1035+
1036+
using (var session = Domain.OpenSession(clientProfile)) {
1037+
var book = session.Query.All<Book>().FirstOrDefault(b => b.Id == bookId);
1038+
1039+
book.Comments.Add(new Comment());
1040+
1041+
var enumerableCount = 0;
1042+
foreach(var comment in book.Comments)
1043+
enumerableCount++;
1044+
Assert.That(enumerableCount, Is.EqualTo(3));
1045+
1046+
Assert.That(book.Comments.Count, Is.EqualTo(3));
1047+
}
1048+
}
1049+
1050+
[Test]
1051+
public void ClientProfileEntitySetCount03()
1052+
{
1053+
long bookId = 0;
1054+
long removingCommentId = 0;
1055+
using (var session = Domain.OpenSession(serverProfile))
1056+
using (var transactionScope = session.OpenTransaction()) {
1057+
var book = new Book() { Title = "First book" };
1058+
1059+
var comment1 = new Comment();
1060+
var comment2 = new Comment();
1061+
var comment3 = new Comment();
1062+
var comment4 = new Comment();
1063+
1064+
book.Comments.Add(comment1);
1065+
book.Comments.Add(comment2);
1066+
book.Comments.Add(comment3);
1067+
book.Comments.Add(comment4);
1068+
1069+
bookId = book.Id;
1070+
removingCommentId = comment3.Id;
1071+
transactionScope.Complete();
1072+
}
1073+
1074+
using (var session = Domain.OpenSession(clientProfile)) {
1075+
var book = session.Query.All<Book>().First(b => b.Id == bookId);
1076+
var removingComment = session.Query.All<Comment>().First(c => c.Id == removingCommentId);
1077+
1078+
var dummyCount = book.Comments.Count;
1079+
book.Comments.Remove(removingComment);
1080+
1081+
Assert.That(book.Comments.Count, Is.EqualTo(3));
1082+
}
1083+
}
1084+
1085+
[Test]
1086+
public void ClientProfileEntitySetCount04()
1087+
{
1088+
long bookId = 0;
1089+
long removingCommentId = 0;
1090+
using (var session = Domain.OpenSession(serverProfile))
1091+
using (var transactionScope = session.OpenTransaction()) {
1092+
var book = new Book() { Title = "First book" };
1093+
1094+
var comment1 = new Comment();
1095+
var comment2 = new Comment();
1096+
var comment3 = new Comment();
1097+
var comment4 = new Comment();
1098+
1099+
book.Comments.Add(comment1);
1100+
book.Comments.Add(comment2);
1101+
book.Comments.Add(comment3);
1102+
book.Comments.Add(comment4);
1103+
1104+
bookId = book.Id;
1105+
removingCommentId = comment3.Id;
1106+
transactionScope.Complete();
1107+
}
1108+
1109+
using (var session = Domain.OpenSession(clientProfile)) {
1110+
var book = session.Query.All<Book>().First(b => b.Id == bookId);
1111+
var removingComment = session.Query.All<Comment>().First(c => c.Id==removingCommentId);
1112+
1113+
book.Comments.Remove(removingComment);
1114+
1115+
var enumerableCount = 0;
1116+
foreach (var comment in book.Comments)
1117+
enumerableCount++;
1118+
Assert.That(enumerableCount, Is.EqualTo(3));
1119+
Assert.That(book.Comments.Count, Is.EqualTo(3));
1120+
}
1121+
}
9891122
}
9901123
}

Orm/Xtensive.Orm/Orm/Internals/EntitySetState.cs

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@ public BackupedState(EntitySetState state)
3838
}
3939

4040
private readonly EntitySetBase owner;
41+
private readonly bool isDisconnected;
4142

4243
private bool isLoaded;
44+
4345
private long? totalItemCount;
4446
private int version;
4547
private IDictionary<Key, Key> addedKeys;
@@ -132,11 +134,10 @@ public bool HasChanges
132134
/// <param name="keys">The keys.</param>
133135
public void Update(IEnumerable<Key> keys, long? count)
134136
{
135-
FetchedKeys.Clear();
136-
TotalItemCount = count;
137-
foreach (var key in keys)
138-
FetchedKeys.Add(key);
139-
Rebind();
137+
if (!isDisconnected)
138+
UpdateStateRegular(keys, count);
139+
else
140+
UpdateStateDisconnected(keys, count);
140141
}
141142

142143
/// <summary>
@@ -321,6 +322,31 @@ IEnumerator IEnumerable.GetEnumerator()
321322

322323
#endregion
323324

325+
326+
private void UpdateStateRegular(IEnumerable<Key> keys, long? count)
327+
{
328+
FetchedKeys.Clear();
329+
TotalItemCount = count;
330+
foreach (var key in keys)
331+
FetchedKeys.Add(key);
332+
Rebind();
333+
}
334+
335+
private void UpdateStateDisconnected(IEnumerable<Key> syncronizedKeys, long? count)
336+
{
337+
FetchedKeys.Clear();
338+
var countExceptRemoved = 0;
339+
foreach (var key in syncronizedKeys) {
340+
FetchedKeys.Add(key);
341+
if (!removedKeys.ContainsKey(key))
342+
countExceptRemoved++;
343+
}
344+
TotalItemCount = count.HasValue
345+
? countExceptRemoved + AddedItemsCount
346+
: count;
347+
Rebind();
348+
}
349+
324350
private void EnsureFetchedKeysIsNotNull()
325351
{
326352
if (FetchedKeys==null)
@@ -332,12 +358,6 @@ private void BackupState()
332358
previousState = new BackupedState(this);
333359
}
334360

335-
//private void InitializeFetchedKeysAndClearChanges()
336-
//{
337-
// InitializeFetchedKeys();
338-
// InitializeDifferenceCollections();
339-
//}
340-
341361
private void InitializeFetchedKeys()
342362
{
343363
FetchedKeys = new LruCache<Key, Key>(WellKnown.EntitySetCacheSize, cachedKey => cachedKey);
@@ -358,6 +378,7 @@ internal EntitySetState(EntitySetBase entitySet)
358378
InitializeDifferenceCollections();
359379
owner = entitySet;
360380
version = int.MinValue;
381+
isDisconnected = entitySet.Session.IsDisconnected;
361382
}
362383
}
363384
}

0 commit comments

Comments
 (0)