From 3cf1611d13b7c9a3dbac00c968d9a81d2e0d62ec Mon Sep 17 00:00:00 2001 From: andypelzer Date: Tue, 28 Oct 2014 21:33:17 +0100 Subject: [PATCH] Added flag prohibiting GraphDiff from ever removing collection elements from the database (owned or associated) --- .../GraphDiff.Tests/GraphDiff.Tests.csproj | 1 + .../Tests/NeverRemoveItemsBehaviors.cs | 86 +++++++++++++++++++ GraphDiff/GraphDiff/GraphDiffConfiguration.cs | 6 ++ .../Internal/Graph/CollectionGraphNode.cs | 3 + 4 files changed, 96 insertions(+) create mode 100644 GraphDiff/GraphDiff.Tests/Tests/NeverRemoveItemsBehaviors.cs diff --git a/GraphDiff/GraphDiff.Tests/GraphDiff.Tests.csproj b/GraphDiff/GraphDiff.Tests/GraphDiff.Tests.csproj index 02231ed..61fe117 100644 --- a/GraphDiff/GraphDiff.Tests/GraphDiff.Tests.csproj +++ b/GraphDiff/GraphDiff.Tests/GraphDiff.Tests.csproj @@ -72,6 +72,7 @@ + diff --git a/GraphDiff/GraphDiff.Tests/Tests/NeverRemoveItemsBehaviors.cs b/GraphDiff/GraphDiff.Tests/Tests/NeverRemoveItemsBehaviors.cs new file mode 100644 index 0000000..a748568 --- /dev/null +++ b/GraphDiff/GraphDiff.Tests/Tests/NeverRemoveItemsBehaviors.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using System.Data.Entity; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using RefactorThis.GraphDiff.Tests.Models; + +namespace RefactorThis.GraphDiff.Tests.Tests +{ + [TestClass] + public class NeverRemoveItemsBehaviors + { + [TestMethod] + public void ShouldNeverRemoveFromAssociatedCollection() + { + var node = new TestNode + { + Title = "New Node", + OneToManyAssociated = new List + { + new OneToManyAssociatedModel { Title = "First One" } + } + }; + + using (var context = new TestDbContext()) + { + context.Nodes.Add(node); + context.SaveChanges(); + } // Simulate detach + + node.OneToManyAssociated.Remove(node.OneToManyAssociated.Single()); + + GraphDiffConfiguration.NeverRemoveFromCollections = true; + + using (var context = new TestDbContext()) + { + node = context.UpdateGraph(node, map => map.AssociatedCollection(p => p.OneToManyAssociated)); + context.SaveChanges(); + + Assert.AreEqual(1, node.OneToManyAssociated.Count); + + var nodeReloaded = context.Nodes.Include(p => p.OneToManyAssociated).Single(p => p.Id == node.Id); + Assert.IsNotNull(nodeReloaded); + Assert.AreEqual(1, nodeReloaded.OneToManyAssociated.Count); + } + } + + [TestMethod] + public void ShouldNeverRemoveFromOwnedCollection() + { + var node = new TestNode + { + Title = "New Node", + OneToManyOwned = new List + { + new OneToManyOwnedModel { Title = "Hello" }, + new OneToManyOwnedModel { Title = "Hello2" }, + new OneToManyOwnedModel { Title = "Hello3" } + } + }; + + using (var context = new TestDbContext()) + { + context.Nodes.Add(node); + context.SaveChanges(); + } // Simulate detach + + node.OneToManyOwned.Remove(node.OneToManyOwned.First()); + node.OneToManyOwned.Remove(node.OneToManyOwned.First()); + node.OneToManyOwned.Remove(node.OneToManyOwned.First()); + + GraphDiffConfiguration.NeverRemoveFromCollections = true; + + using (var context = new TestDbContext()) + { + node = context.UpdateGraph(node, map => map.OwnedCollection(p => p.OneToManyOwned)); + context.SaveChanges(); + + Assert.AreEqual(3, node.OneToManyOwned.Count); + + var reloadedNode = context.Nodes.Include(p => p.OneToManyOwned).Single(p => p.Id == node.Id); + Assert.IsNotNull(reloadedNode); + Assert.AreEqual(3, reloadedNode.OneToManyOwned.Count); + } + } + } +} diff --git a/GraphDiff/GraphDiff/GraphDiffConfiguration.cs b/GraphDiff/GraphDiff/GraphDiffConfiguration.cs index 9aaf2b0..4c68282 100644 --- a/GraphDiff/GraphDiff/GraphDiffConfiguration.cs +++ b/GraphDiff/GraphDiff/GraphDiffConfiguration.cs @@ -16,5 +16,11 @@ public static class GraphDiffConfiguration /// to ensure the EF local cache has the latest state. /// public static bool ReloadAssociatedEntitiesWhenAttached { get; set; } + + /// + /// If GraphDiff encounters an entity in a database collection that is no longer part of the graph it is + /// currently attaching, it will remove that element from the database as well unless this flag is set. + /// + public static bool NeverRemoveFromCollections { get; set; } } } diff --git a/GraphDiff/GraphDiff/Internal/Graph/CollectionGraphNode.cs b/GraphDiff/GraphDiff/Internal/Graph/CollectionGraphNode.cs index 39d17a9..39cad9c 100644 --- a/GraphDiff/GraphDiff/Internal/Graph/CollectionGraphNode.cs +++ b/GraphDiff/GraphDiff/Internal/Graph/CollectionGraphNode.cs @@ -101,6 +101,9 @@ private void UpdateElement(IChangeTracker changeTracker, IEntityManager entit private void RemoveElement(IChangeTracker changeTracker, object dbItem, object dbCollection) { + if (GraphDiffConfiguration.NeverRemoveFromCollections) + return; + dbCollection.GetType().GetMethod("Remove").Invoke(dbCollection, new[] { dbItem }); changeTracker.AttachRequiredNavigationProperties(dbItem, dbItem);