diff --git a/Source/Tests/TrackableEntities.Client.Tests.Entities/NorthwindModels/PriorityOrder.cs b/Source/Tests/TrackableEntities.Client.Tests.Entities/NorthwindModels/PriorityOrder.cs
new file mode 100644
index 00000000..0a0118dd
--- /dev/null
+++ b/Source/Tests/TrackableEntities.Client.Tests.Entities/NorthwindModels/PriorityOrder.cs
@@ -0,0 +1,21 @@
+using System;
+using Newtonsoft.Json;
+
+namespace TrackableEntities.Client.Tests.Entities.NorthwindModels
+{
+ [JsonObject(IsReference = true)]
+ public class PriorityOrder : Order
+ {
+ private string _priorityPlan;
+ public string PriorityPlan
+ {
+ get { return _priorityPlan; }
+ set
+ {
+ if (value == _priorityPlan) return;
+ _priorityPlan = value;
+ NotifyPropertyChanged(() => PriorityPlan);
+ }
+ }
+ }
+}
diff --git a/Source/Tests/TrackableEntities.Client.Tests.Entities/TrackableEntities.Client.Tests.Entities.csproj b/Source/Tests/TrackableEntities.Client.Tests.Entities/TrackableEntities.Client.Tests.Entities.csproj
index 7fbc899b..243b33f0 100644
--- a/Source/Tests/TrackableEntities.Client.Tests.Entities/TrackableEntities.Client.Tests.Entities.csproj
+++ b/Source/Tests/TrackableEntities.Client.Tests.Entities/TrackableEntities.Client.Tests.Entities.csproj
@@ -53,6 +53,7 @@
+
diff --git a/Source/Tests/TrackableEntities.Client.Tests.Extensions/ChangeTrackingExtensionsTests.cs b/Source/Tests/TrackableEntities.Client.Tests.Extensions/ChangeTrackingExtensionsTests.cs
index 23eb9e3c..924f7d7a 100644
--- a/Source/Tests/TrackableEntities.Client.Tests.Extensions/ChangeTrackingExtensionsTests.cs
+++ b/Source/Tests/TrackableEntities.Client.Tests.Extensions/ChangeTrackingExtensionsTests.cs
@@ -122,8 +122,9 @@ public void MergeChanges_Should_Set_TrackingState_To_Unchanged_For_Added_Order_W
{
// Arrange
var database = new MockNorthwind();
- var origOrder = new Order
+ var origOrder = new PriorityOrder
{
+ PriorityPlan = "Silver",
OrderDate = DateTime.Parse("1996-07-04"),
CustomerId = "ALFKI"
};
diff --git a/Source/Tests/TrackableEntities.EF.5.Tests/NorthwindDbContextTests.cs b/Source/Tests/TrackableEntities.EF.5.Tests/NorthwindDbContextTests.cs
index 8940a409..24d4aa34 100644
--- a/Source/Tests/TrackableEntities.EF.5.Tests/NorthwindDbContextTests.cs
+++ b/Source/Tests/TrackableEntities.EF.5.Tests/NorthwindDbContextTests.cs
@@ -399,6 +399,27 @@ public void Apply_Changes_Should_Mark_Order_Modified_With_OrderDetails_Added_Mod
Assert.AreEqual(EntityState.Modified, context.Entry(detail2).State);
Assert.AreEqual(EntityState.Deleted, context.Entry(detail3).State);
Assert.AreEqual(EntityState.Unchanged, context.Entry(detail4).State);
+ Assert.AreEqual(EntityState.Unchanged, context.Entry(detail1.Product).State);
+ }
+
+ [Test]
+ public void Apply_Changes_Should_Mark_Unchanged_Product_Of_Added_OrderDetail_Of_Added_Order_As_Unchanged()
+ {
+ // Arrange
+ var context = TestsHelper.CreateNorthwindDbContext(CreateNorthwindDbOptions);
+ var order = new MockNorthwind().Orders[0];
+ var orderDetail = order.OrderDetails[0];
+ var product = orderDetail.Product;
+ order.TrackingState = TrackingState.Added;
+ orderDetail.TrackingState = TrackingState.Added;
+
+ // Act
+ context.ApplyChanges(order);
+
+ // Assert
+ Assert.AreEqual(EntityState.Added, context.Entry(order).State);
+ Assert.AreEqual(EntityState.Added, context.Entry(orderDetail).State);
+ Assert.AreEqual(EntityState.Unchanged, context.Entry(product).State);
}
[Test]
diff --git a/Source/TrackableEntities.Client/ChangeTrackingExtensions.cs b/Source/TrackableEntities.Client/ChangeTrackingExtensions.cs
index 36b80596..ddd58c09 100644
--- a/Source/TrackableEntities.Client/ChangeTrackingExtensions.cs
+++ b/Source/TrackableEntities.Client/ChangeTrackingExtensions.cs
@@ -221,7 +221,7 @@ private static void SetEntityProperties(this ITrackable targetItem, ITrackable s
#if SILVERLIGHT || NET40
foreach (var prop in targetItem.GetType().GetProperties().Where(p => p.CanWrite)
#else
- foreach (var prop in targetItem.GetType().GetTypeInfo().DeclaredProperties
+ foreach (var prop in targetItem.GetType().BaseTypes().SelectMany(t => t.GetTypeInfo().DeclaredProperties)
.Where(p => p.CanWrite && !p.GetMethod.IsPrivate)
#endif
.Except(targetItem.GetNavigationProperties(false).Select(np => np.Property)))
diff --git a/Source/TrackableEntities.EF.5/DbContextExtensions.cs b/Source/TrackableEntities.EF.5/DbContextExtensions.cs
index 2154a50d..4ad43fc0 100644
--- a/Source/TrackableEntities.EF.5/DbContextExtensions.cs
+++ b/Source/TrackableEntities.EF.5/DbContextExtensions.cs
@@ -97,13 +97,11 @@ private static void ApplyChanges(this DbContext context,
// Set state for child collections
context.ApplyChangesOnProperties(item, visitationHelper);
return;
- }
+ }
- // Exit if parent is added or deleted,
- // and it's not a M-1 relation
+ // Exit if parent is deleted and not a M-1 relation
if (parent != null
- && (parent.TrackingState == TrackingState.Added
- || parent.TrackingState == TrackingState.Deleted)
+ && (parent.TrackingState == TrackingState.Deleted)
&& !context.IsRelatedProperty(parent.GetType(),
propertyName, RelationshipType.ManyToOne))
return;
@@ -126,9 +124,14 @@ private static void ApplyChanges(this DbContext context,
return;
}
- // Set state to Added on parent only
+ // Set state to Added if item marked as Added
if (item.TrackingState == TrackingState.Added
- && (state == null || state == TrackingState.Added))
+ && (state == null || state == TrackingState.Added)
+ // Or if parent marked as Added and 1-M or 1-1 relation
+ || (parent != null
+ && parent.TrackingState == TrackingState.Added
+ && (context.IsRelatedProperty(parent.GetType(), propertyName, RelationshipType.OneToMany)
+ || context.IsRelatedProperty(parent.GetType(), propertyName, RelationshipType.OneToOne))))
{
context.Entry(item).State = EntityState.Added;
context.ApplyChangesOnProperties(item, visitationHelper);
@@ -565,6 +568,9 @@ private static bool IsRelatedProperty(this DbContext dbContext,
case RelationshipType.ManyToMany:
return navProp.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many
&& navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many;
+ case RelationshipType.OneToMany:
+ return navProp.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One
+ && navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many;
default:
return false;
}
@@ -603,6 +609,7 @@ enum RelationshipType
ManyToOne,
OneToOne,
ManyToMany,
+ OneToMany
}
#endregion