private void RemoveColumnMapping(IStructuralTypeMapping structuralTypeMapping, IEnumerable <EdmProperty> propertyPath)
        {
            DebugCheck.NotNull(structuralTypeMapping);
            DebugCheck.NotNull(propertyPath);

            // Remove the target column mapping by walking down the mapping fragment
            // tree corresponding to the passed-in property path until we reach the scalar
            // mapping leaf node. On the way out remove any empty mappings.

            var propertyMapping
                = structuralTypeMapping
                  .Properties
                  .Single(pm => ReferenceEquals(pm.EdmProperty, propertyPath.First()));

            if (propertyMapping is StorageScalarPropertyMapping)
            {
                structuralTypeMapping.RemoveProperty(propertyMapping);
            }
            else
            {
                var complexPropertyMapping = ((StorageComplexPropertyMapping)propertyMapping);
                var complexTypeMapping     = complexPropertyMapping.TypeMappings.Single();

                RemoveColumnMapping(complexTypeMapping, propertyPath.Skip(1));

                if (!complexTypeMapping.Properties.Any())
                {
                    structuralTypeMapping.RemoveProperty(complexPropertyMapping);
                }
            }
        }
        public void AddColumnMapping(ColumnMappingBuilder columnMappingBuilder)
        {
            DebugCheck.NotNull(columnMappingBuilder);
            DebugCheck.NotNull(columnMappingBuilder.ColumnProperty);
            Debug.Assert(columnMappingBuilder.PropertyPath.Any());
            Debug.Assert(!_columnMappings.Contains(columnMappingBuilder));

            _columnMappings.Add(columnMappingBuilder);

            IStructuralTypeMapping structuralTypeMapping = this;
            EdmProperty            property;

            // Turn the property path into a mapping fragment nested tree structure.

            var i = 0;

            for (; i < columnMappingBuilder.PropertyPath.Count - 1; i++)
            {
                // The first n-1 properties are complex so we just need to build
                // a corresponding tree of complex type mappings.

                property = columnMappingBuilder.PropertyPath[i];

                var complexPropertyMapping
                    = structuralTypeMapping
                      .Properties
                      .OfType <StorageComplexPropertyMapping>()
                      .SingleOrDefault(pm => ReferenceEquals(pm.EdmProperty, property));

                StorageComplexTypeMapping complexTypeMapping = null;

                if (complexPropertyMapping == null)
                {
                    complexTypeMapping = new StorageComplexTypeMapping(false);
                    complexTypeMapping.AddType(property.ComplexType);

                    complexPropertyMapping = new StorageComplexPropertyMapping(property);
                    complexPropertyMapping.AddTypeMapping(complexTypeMapping);

                    structuralTypeMapping.AddProperty(complexPropertyMapping);
                }

                structuralTypeMapping
                    = complexTypeMapping
                      ?? complexPropertyMapping.TypeMappings.Single();
            }

            // The last property has to be a scalar mapping to the target column.
            // Extract it and create the scalar mapping leaf node, ensuring that we
            // set the target column.

            property = columnMappingBuilder.PropertyPath[i];

            var scalarPropertyMapping
                = structuralTypeMapping
                  .Properties
                  .OfType <StorageScalarPropertyMapping>()
                  .SingleOrDefault(pm => ReferenceEquals(pm.EdmProperty, property));

            if (scalarPropertyMapping == null)
            {
                scalarPropertyMapping
                    = new StorageScalarPropertyMapping(property, columnMappingBuilder.ColumnProperty);

                structuralTypeMapping.AddProperty(scalarPropertyMapping);

                columnMappingBuilder.SetTarget(scalarPropertyMapping);
            }
            else
            {
                scalarPropertyMapping.ColumnProperty = columnMappingBuilder.ColumnProperty;
            }
        }