IGNITE-4415 .NET: Fix duplicate entity set handling in EntityFramework caching
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/781e5b7c Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/781e5b7c Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/781e5b7c Branch: refs/heads/ignite-2.0 Commit: 781e5b7c93a1ee47299fc94519efbd0bea020940 Parents: 6ca8670 Author: Pavel Tupitsyn <[email protected]> Authored: Fri Dec 23 16:53:59 2016 +0300 Committer: Pavel Tupitsyn <[email protected]> Committed: Fri Dec 23 16:54:35 2016 +0300 ---------------------------------------------------------------------- .../EntityFrameworkCacheTest.cs | 54 +++++++++++++++++++- .../Impl/DbCommandInfo.cs | 21 +++++++- 2 files changed, 72 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/781e5b7c/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/EntityFrameworkCacheTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/EntityFrameworkCacheTest.cs b/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/EntityFrameworkCacheTest.cs index 0e095f4..158df12 100644 --- a/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/EntityFrameworkCacheTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/EntityFrameworkCacheTest.cs @@ -321,6 +321,55 @@ namespace Apache.Ignite.EntityFramework.Tests } /// <summary> + /// Queries with entity sets used multiple times are handled correctly. + /// </summary> + [Test] + public void TestDuplicateEntitySets() + { + using (var ctx = GetDbContext()) + { + var blog = new Blog + { + Name = "Foo", + Posts = new List<Post> + { + new Post {Title = "Foo"}, + new Post {Title = "Foo"}, + new Post {Title = "Foo"}, + new Post {Title = "Bar"} + } + }; + ctx.Blogs.Add(blog); + + Assert.AreEqual(5, ctx.SaveChanges()); + + var res = ctx.Blogs.Select(b => new + { + X = b.Posts.FirstOrDefault(p => p.Title == b.Name), + Y = b.Posts.Count(p => p.Title == b.Name) + }).ToArray(); + + Assert.AreEqual(1, res.Length); + Assert.AreEqual("Foo", res[0].X.Title); + Assert.AreEqual(3, res[0].Y); + + // Modify and check updated result. + ctx.Posts.Remove(ctx.Posts.First(x => x.Title == "Foo")); + Assert.AreEqual(1, ctx.SaveChanges()); + + res = ctx.Blogs.Select(b => new + { + X = b.Posts.FirstOrDefault(p => p.Title == b.Name), + Y = b.Posts.Count(p => p.Title == b.Name) + }).ToArray(); + + Assert.AreEqual(1, res.Length); + Assert.AreEqual("Foo", res[0].X.Title); + Assert.AreEqual(2, res[0].Y); + } + } + + /// <summary> /// Tests transactions created with BeginTransaction. /// </summary> [Test] @@ -664,8 +713,11 @@ namespace Apache.Ignite.EntityFramework.Tests { TestUtils.RunMultiThreaded(CreateRemoveBlog, 4, 5); + // Run once again to force cleanup. + CreateRemoveBlog(); + // Wait for the cleanup to complete. - Thread.Sleep(2000); + Thread.Sleep(1000); // Only one version of data is in the cache. Assert.AreEqual(1, _cache.GetSize()); http://git-wip-us.apache.org/repos/asf/ignite/blob/781e5b7c/modules/platforms/dotnet/Apache.Ignite.EntityFramework/Impl/DbCommandInfo.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.EntityFramework/Impl/DbCommandInfo.cs b/modules/platforms/dotnet/Apache.Ignite.EntityFramework/Impl/DbCommandInfo.cs index 7f18170..6b5db05 100644 --- a/modules/platforms/dotnet/Apache.Ignite.EntityFramework/Impl/DbCommandInfo.cs +++ b/modules/platforms/dotnet/Apache.Ignite.EntityFramework/Impl/DbCommandInfo.cs @@ -127,6 +127,7 @@ namespace Apache.Ignite.EntityFramework.Impl expression.Accept(visitor); + // Should be sorted and unique. return visitor.EntitySets.ToArray(); } @@ -135,8 +136,9 @@ namespace Apache.Ignite.EntityFramework.Impl /// </summary> private class ScanExpressionVisitor : BasicCommandTreeVisitor { - /** */ - private readonly List<EntitySetBase> _entitySets = new List<EntitySetBase>(); + /** Unique and sorted entity sets. */ + private readonly SortedSet<EntitySetBase> _entitySets = + new SortedSet<EntitySetBase>(EntitySetComparer.Instance); /// <summary> /// Gets the entity sets. @@ -154,5 +156,20 @@ namespace Apache.Ignite.EntityFramework.Impl base.Visit(expression); } } + + /// <summary> + /// Compares entity sets by name. + /// </summary> + private class EntitySetComparer : IComparer<EntitySetBase> + { + /** Default instance. */ + public static readonly EntitySetComparer Instance = new EntitySetComparer(); + + /** <inheritdoc /> */ + public int Compare(EntitySetBase x, EntitySetBase y) + { + return string.CompareOrdinal(x.Name, y.Name); + } + } } }
