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 AssertStateOfAddressProperties(DbComplexPropertyEntry<Building, Address> addressEntry, string city,
                                                    string state, string environment, bool isModified)
        {
            Assert.Equal(isModified, addressEntry.IsModified);
            Assert.Equal(isModified, addressEntry.Property(a => a.City).IsModified);
            Assert.Equal(isModified, addressEntry.Property(a => a.State).IsModified);
            Assert.Equal(isModified,
                         addressEntry.ComplexProperty(a => a.SiteInfo).Property(s => s.Environment).IsModified);

            Assert.Equal(city, addressEntry.Property(a => a.City).CurrentValue);
            Assert.Equal(state, addressEntry.Property(a => a.State).CurrentValue);
            Assert.Equal(environment,
                         addressEntry.ComplexProperty(a => a.SiteInfo).Property(s => s.Environment).CurrentValue);

            Assert.Equal(isModified ? EntityState.Modified : EntityState.Unchanged, addressEntry.EntityEntry.State);
        }