private Address CloneAddress(Address source) { return new Address { Street = source.Street, City = source.City, State = source.State, ZipCode = source.ZipCode, SiteInfo = CloneSiteInfo(source.SiteInfo) }; }
private void TestComplexCurentValue(DbEntityEntry<Building> entityEntry, DbComplexPropertyEntry<Building, Address> propertyEntry, Func<Address> getter) { var initialState = entityEntry.State; // Get these nested entries at the beginning and check that they remain in sync var cityEntry = propertyEntry.Property(a => a.City); var environmentEntry = propertyEntry.ComplexProperty(a => a.SiteInfo).Property(i => i.Environment); Assert.Equal(initialState == EntityState.Modified, propertyEntry.IsModified); Assert.Equal("Redmond", propertyEntry.CurrentValue.City); Assert.Equal("Clean", propertyEntry.CurrentValue.SiteInfo.Environment); Assert.Equal("Redmond", cityEntry.CurrentValue); Assert.Equal("Clean", environmentEntry.CurrentValue); // Getting complex object should return actual object Assert.Same(getter(), propertyEntry.CurrentValue); // Set to same value; prop should not get marked as modified propertyEntry.CurrentValue = getter(); Assert.Equal(initialState == EntityState.Modified, propertyEntry.IsModified); Assert.Equal(initialState, entityEntry.State); // Set to new object with the same values; should get marked as modified var sameAddress = CloneAddress(getter()); propertyEntry.CurrentValue = sameAddress; Assert.Equal("Redmond", propertyEntry.CurrentValue.City); Assert.Equal("Clean", propertyEntry.CurrentValue.SiteInfo.Environment); Assert.Equal("Redmond", cityEntry.CurrentValue); Assert.Equal("Clean", environmentEntry.CurrentValue); CheckPropertyIsModified(entityEntry, (DbComplexPropertyEntry)propertyEntry, initialState); Assert.Same(sameAddress, getter()); // Reset state if (initialState == EntityState.Unchanged) { entityEntry.State = EntityState.Unchanged; } // Set to new value; prop marked as modified var newAddress = new Address { Street = "300 Main St", City = "Ames", State = "IA", ZipCode = "50010", SiteInfo = new SiteInfo { Zone = 2, Environment = "Contaminated" } }; propertyEntry.CurrentValue = newAddress; Assert.Equal("Ames", propertyEntry.CurrentValue.City); Assert.Equal("Contaminated", propertyEntry.CurrentValue.SiteInfo.Environment); Assert.Equal("Ames", cityEntry.CurrentValue); Assert.Equal("Contaminated", environmentEntry.CurrentValue); CheckPropertyIsModified(entityEntry, (DbComplexPropertyEntry)propertyEntry, initialState); Assert.Same(newAddress, getter()); // New value reflected in record if (initialState != EntityState.Deleted && initialState != EntityState.Detached) { var addressValues = (DbPropertyValues)entityEntry.CurrentValues["Address"]; var siteValues = (DbPropertyValues)addressValues["SiteInfo"]; Assert.Equal("Ames", addressValues["City"]); Assert.Equal("Contaminated", siteValues["Environment"]); // Change record; new value reflected in entry addressValues["City"] = "Cedar Falls"; siteValues["Environment"] = "Peachy"; Assert.Equal("Cedar Falls", propertyEntry.CurrentValue.City); Assert.Equal("Peachy", propertyEntry.CurrentValue.SiteInfo.Environment); } // Set to null Assert.Throws<InvalidOperationException>(() => propertyEntry.CurrentValue = null).ValidateMessage( "DbPropertyValues_ComplexObjectCannotBeNull", "Address", "Building"); // Set to new value that has a nested null complex object // Should always throw, but currently only throws if the entity is Added/Modified/Unchanged if (initialState != EntityState.Detached && initialState != EntityState.Deleted) { var addressWithNull = new Address { Street = "300 Main St", City = "Ames", State = "IA", ZipCode = "50010", SiteInfo = null }; Assert.Throws<InvalidOperationException>(() => propertyEntry.CurrentValue = addressWithNull). ValidateMessage("DbPropertyValues_ComplexObjectCannotBeNull", "SiteInfo", "Address"); } }
private void TestComplexOriginalValue(DbEntityEntry<Building> entityEntry, DbPropertyEntry<Building, Address> propertyEntry) { var initialState = entityEntry.State; if (initialState == EntityState.Added) { Assert.Throws<InvalidOperationException>(() => { var _ = propertyEntry.OriginalValue; }).ValidateMessage ("DbPropertyValues_CannotGetValuesForState", "OriginalValues", "Added"); Assert.Throws<InvalidOperationException>(() => propertyEntry.OriginalValue = new Address()). ValidateMessage("DbPropertyValues_CannotGetValuesForState", "OriginalValues", "Added"); return; } if (initialState == EntityState.Detached) { Assert.Throws<InvalidOperationException>(() => { var _ = propertyEntry.OriginalValue; }).ValidateMessage ("DbPropertyEntry_NotSupportedForDetached", "OriginalValue", propertyEntry.Name, entityEntry.Entity.GetType().Name); Assert.Throws<InvalidOperationException>(() => propertyEntry.OriginalValue = new Address()). ValidateMessage("DbPropertyEntry_NotSupportedForDetached", "OriginalValue", propertyEntry.Name, entityEntry.Entity.GetType().Name); return; } Assert.Equal(initialState == EntityState.Modified, propertyEntry.IsModified); Assert.Equal("Redmond", propertyEntry.OriginalValue.City); Assert.Equal("Clean", propertyEntry.OriginalValue.SiteInfo.Environment); // Set to new object with the same values; should not get marked as modified because no values changing var sameAddress = CloneAddress(propertyEntry.OriginalValue); propertyEntry.OriginalValue = sameAddress; Assert.Equal("Redmond", propertyEntry.OriginalValue.City); Assert.Equal("Clean", propertyEntry.OriginalValue.SiteInfo.Environment); Assert.Equal(initialState == EntityState.Modified, propertyEntry.IsModified); Assert.Equal(initialState, entityEntry.State); // Set to new value; prop marked as modified var newAddress = new Address { Street = "300 Main St", City = "Ames", State = "IA", ZipCode = "50010", SiteInfo = new SiteInfo { Zone = 2, Environment = "Contaminated" } }; propertyEntry.OriginalValue = newAddress; Assert.Equal("Ames", propertyEntry.OriginalValue.City); Assert.Equal("Contaminated", propertyEntry.OriginalValue.SiteInfo.Environment); CheckPropertyIsModified(entityEntry, propertyEntry, initialState); // New value reflected in record if (initialState != EntityState.Added && initialState != EntityState.Detached) { var addressValues = (DbPropertyValues)entityEntry.OriginalValues["Address"]; var siteValues = (DbPropertyValues)addressValues["SiteInfo"]; Assert.Equal("Ames", addressValues["City"]); Assert.Equal("Contaminated", siteValues["Environment"]); // Change record; new value reflected in entry addressValues["City"] = "Cedar Falls"; siteValues["Environment"] = "Peachy"; Assert.Equal("Cedar Falls", propertyEntry.OriginalValue.City); Assert.Equal("Peachy", propertyEntry.OriginalValue.SiteInfo.Environment); } // Set to null Assert.Throws<InvalidOperationException>(() => propertyEntry.OriginalValue = null).ValidateMessage( "DbPropertyValues_ComplexObjectCannotBeNull", "Address", "Building"); // Set to new value that has a nested null complex object // Should always throw, but Originally only throws if the entity is Added/Modified/Unchanged if (initialState != EntityState.Detached && initialState != EntityState.Deleted) { var addressWithNull = new Address { Street = "300 Main St", City = "Ames", State = "IA", ZipCode = "50010", SiteInfo = null }; Assert.Throws<InvalidOperationException>(() => propertyEntry.OriginalValue = addressWithNull). ValidateMessage("DbPropertyValues_ComplexObjectCannotBeNull", "SiteInfo", "Address"); } }