private List<Employee> UpdateEmployeesWithTerritories(IEnumerable<Employee> changes)
        {
            var updatedEmployees = new List<Employee>();
            foreach (var origEmployee in changes)
            {
                // Simulate serialization
                var updatedEmployee = origEmployee.Clone<Employee>();

                // Simulate load related entities
                var addedNewTerritory = updatedEmployee.Territories.Single(t => t.TerritoryId == "91360");
                var modifiedTerritory = updatedEmployee.Territories.Single(t => t.TerritoryId == "01730");
                var area5 = new Area { AreaId = 5, AreaName = "Southwestern", 
                    Territories = new ChangeTrackingCollection<Territory> { addedNewTerritory }};
                var area6 = new Area { AreaId = 6, AreaName = "Central", 
                    Territories = new ChangeTrackingCollection<Territory> { modifiedTerritory }};
                addedNewTerritory.Area = area5;
                modifiedTerritory.Area = area6;

                // Simulate db-generated values
                addedNewTerritory.Data = "yyy";

                updatedEmployee.AcceptChanges();
                updatedEmployees.Add(updatedEmployee);
            }
            return updatedEmployees;
        }
        public void MergeChanges_Should_Merge_Updates_For_Unchanged_Employee_With_Changed_Territories()
        {
            // Arrange
            var database = new MockNorthwind();
            var employee = database.Employees[0];
            var unchangedTerritory = employee.Territories[0];
            var modifiedTerritory = employee.Territories[1];
            var deletedTerritory = employee.Territories[2];
            var addedExistingTerritory = database.Territories[3];
            var area1 = new Area { AreaId = 1, AreaName = "Northern", Territories = new ChangeTrackingCollection<Territory> { unchangedTerritory } };
            var area2 = new Area { AreaId = 2, AreaName = "Southern", Territories = new ChangeTrackingCollection<Territory> { modifiedTerritory } };
            var area3 = new Area { AreaId = 3, AreaName = "Eastern", Territories = new ChangeTrackingCollection<Territory> { deletedTerritory } };
            var area4 = new Area { AreaId = 4, AreaName = "Western", Territories = new ChangeTrackingCollection<Territory> { addedExistingTerritory } };
            var addedNewTerritory = new Territory
            {
                TerritoryId = "91360",
                TerritoryDescription = "SouthernCalifornia",
                Employees = new ChangeTrackingCollection<Employee> { employee },
                AreaId = 5,
                TrackingState = TrackingState.Added // Must explicitly mark as added
            };
            unchangedTerritory.Area = area1;
            unchangedTerritory.AreaId = area1.AreaId;
            modifiedTerritory.Area = area2;
            modifiedTerritory.AreaId = area2.AreaId;
            deletedTerritory.Area = area3;
            deletedTerritory.AreaId = area3.AreaId;
            addedExistingTerritory.Area = area4;
            addedExistingTerritory.AreaId = area4.AreaId;

            var changeTracker = new ChangeTrackingCollection<Employee>(employee);
            modifiedTerritory.TerritoryDescription = "xxx"; // mod prop
            modifiedTerritory.AreaId = 6; // mod FK prop
            employee.Territories.Remove(deletedTerritory); // should mark area deleted
            employee.Territories.Add(addedExistingTerritory); // should keep area unchanged
            employee.Territories.Add(addedNewTerritory); // should keep territory added
            addedExistingTerritory.Area.AreaName = "zzz"; // should mark area modified

            var changes = changeTracker.GetChanges(); // should exclude unchanged territory
            var updatedEmployee = UpdateEmployeesWithTerritories(changes)[0]; // rel entities, db-gen vals

            // Act
            changeTracker.MergeChanges(updatedEmployee);

            // Assert
            Assert.Contains(unchangedTerritory, employee.Territories); // Unchanged present
            Assert.Equal("zzz", addedExistingTerritory.Area.AreaName); // Area name updated
            Assert.Equal("yyy", addedNewTerritory.Data); // Db-generated value set
            Assert.Equal(addedNewTerritory.AreaId, addedNewTerritory.Area.AreaId); // Added territory Area set
            Assert.Equal(modifiedTerritory.AreaId, modifiedTerritory.Area.AreaId); // Modified territory Area set
            Assert.Same(addedExistingTerritory, employee.Territories.Single(t => t.TerritoryId == "02116")); // Ref equality
            Assert.Same(addedNewTerritory, employee.Territories.Single(t => t.TerritoryId == "91360")); // Ref equality
            Assert.Same(modifiedTerritory, employee.Territories.Single(t => t.TerritoryId == "01730")); // Ref equality
            Assert.DoesNotContain(deletedTerritory, employee.Territories); // Detail deleted
            ICollection cachedDeletes = ((ITrackingCollection)employee.Territories).GetChanges(true);
            Assert.Empty(cachedDeletes); // Cached deletes have been removed
        }
        public void GetChanges_On_Existing_Employee_With_Territory_And_Modified_Area_Should_Return_Marked_Territory()
        {
            // Ensure that changes are retrieved across M-M relationships.

            // Arrange
            var database = new MockNorthwind();
            var employee = database.Employees[0];
            var territory = employee.Territories[0];
            var area = new Area
            {
                AreaId = 1,
                AreaName = "Northern",
                TrackingState = TrackingState.Modified
            };
            territory.AreaId = 1;
            territory.Area = area;
            var changeTracker = new ChangeTrackingCollection<Employee>(employee);
            area.AreaName = "xxx"; // Modify area

            // Act
            var changes = changeTracker.GetChanges();
            var changedEmployee = changes.First();
            var changedTerritory = changedEmployee.Territories.Single(t => t.TerritoryId == territory.TerritoryId);
            var changedArea = changedTerritory.Area;

            // Assert
            Assert.Equal(TrackingState.Unchanged, changedEmployee.TrackingState);
            Assert.Equal(TrackingState.Unchanged, changedTerritory.TrackingState);
            Assert.Equal(TrackingState.Modified, changedArea.TrackingState);
            Assert.Contains("AreaName", area.ModifiedProperties);
        }