internal void Configure(
            EdmEntityType entityType,
            DbDatabaseMapping databaseMapping,
            DbProviderManifest providerManifest)
        {
            Contract.Requires(entityType != null);
            Contract.Requires(databaseMapping != null);
            Contract.Requires(providerManifest != null);

            var entityTypeMapping
                = databaseMapping.GetEntityTypeMapping(entityType.GetClrType());

            if (entityTypeMapping != null)
            {
                VerifyAllCSpacePropertiesAreMapped(
                    databaseMapping.GetEntityTypeMappings(entityType),
                    entityTypeMapping.EntityType.DeclaredProperties,
                    new List<EdmProperty>());
            }

            ConfigurePropertyMappings(databaseMapping, entityType, providerManifest);
            ConfigureAssociationMappings(databaseMapping, entityType);
            ConfigureDependentKeys(databaseMapping);
        }
        public void GetEntityTypeMapping_should_return_mapping_for_type_by_clrType()
        {
            var databaseMapping = new DbDatabaseMapping()
                .Initialize(new EdmModel().Initialize(), new DbDatabaseMetadata());
            var entityType = new EdmEntityType { Name = "Foo" };
            entityType.SetClrType(typeof(object));
            var entityTypeMapping = new DbEntityTypeMapping { EntityType = entityType };
            entityTypeMapping.SetClrType(typeof(object));
            databaseMapping.AddEntitySetMapping(new EdmEntitySet()).EntityTypeMappings.Add(entityTypeMapping);

            Assert.Same(entityTypeMapping, databaseMapping.GetEntityTypeMapping(typeof(object)));
        }
 internal static void ConfigureUnconfiguredType(
     DbDatabaseMapping databaseMapping, DbProviderManifest providerManifest, EdmEntityType entityType)
 {
     var c = new EntityMappingConfiguration();
     var entityTypeMapping
         = databaseMapping.GetEntityTypeMapping(entityType.GetClrType());
     c.Configure(databaseMapping, providerManifest, entityType, ref entityTypeMapping, false, 0, 1);
 }
        private static void UpdatePrincipalTables(
            DbDatabaseMapping databaseMapping, DbTableMetadata toTable, bool removeFks,
            EdmAssociationType associationType, EdmEntityType et)
        {
            EdmAssociationEnd principalEnd, dependentEnd;
            var endsToCheck = new List<EdmAssociationEnd>();
            if (associationType.TryGuessPrincipalAndDependentEnds(out principalEnd, out dependentEnd))
            {
                endsToCheck.Add(principalEnd);
            }
            else if (associationType.SourceEnd.EndKind == EdmAssociationEndKind.Many
                     && associationType.TargetEnd.EndKind == EdmAssociationEndKind.Many)
            {
                // many to many consider both ends
                endsToCheck.Add(associationType.SourceEnd);
                endsToCheck.Add(associationType.TargetEnd);
            }
            else
            {
                // 1:1 and 0..1:0..1
                endsToCheck.Add(associationType.SourceEnd);
            }

            foreach (var end in endsToCheck)
            {
                if (end.EntityType == et)
                {
                    IEnumerable<KeyValuePair<DbTableMetadata, IEnumerable<DbTableColumnMetadata>>> dependentTableInfos;
                    if (associationType.Constraint != null)
                    {
                        var originalDependentType = associationType.GetOtherEnd(end).EntityType;
                        var allDependentTypes = databaseMapping.Model.GetSelfAndAllDerivedTypes(originalDependentType);

                        dependentTableInfos =
                            allDependentTypes.Select(t => databaseMapping.GetEntityTypeMapping(t)).Where(
                                dm => dm != null)
                                .SelectMany(
                                    dm => dm.TypeMappingFragments
                                              .Where(
                                                  tmf => associationType.Constraint.DependentProperties
                                                             .All(
                                                                 p =>
                                                                 tmf.PropertyMappings.Any(
                                                                     pm => pm.PropertyPath.First() == p))))
                                .Distinct((f1, f2) => f1.Table == f2.Table)
                                .Select(
                                    df =>
                                    new KeyValuePair<DbTableMetadata, IEnumerable<DbTableColumnMetadata>>(
                                        df.Table,
                                        df.PropertyMappings.Where(
                                            pm =>
                                            associationType.Constraint.DependentProperties.Contains(
                                                pm.PropertyPath.First())).Select(
                                                    pm => pm.Column)));
                    }
                    else
                    {
                        // IA
                        var associationSetMapping =
                            databaseMapping.EntityContainerMappings.Single().AssociationSetMappings.Where(
                                asm => asm.AssociationSet.ElementType == associationType).Single();
                        var dependentTable = associationSetMapping.Table;
                        var propertyMappings = associationSetMapping.SourceEndMapping.AssociationEnd == end
                                                   ? associationSetMapping.SourceEndMapping.PropertyMappings
                                                   : associationSetMapping.TargetEndMapping.PropertyMappings;
                        var dependentColumns = propertyMappings.Select(pm => pm.Column);

                        dependentTableInfos = new[]
                            {
                                new KeyValuePair
                                    <DbTableMetadata, IEnumerable<DbTableColumnMetadata>>(
                                    dependentTable, dependentColumns)
                            };
                    }

                    foreach (var tableInfo in dependentTableInfos)
                    {
                        foreach (
                            var fk in
                                tableInfo.Key.ForeignKeyConstraints.Where(
                                    fk => fk.DependentColumns.SequenceEqual(tableInfo.Value)).ToArray(
                                        
                                    ))
                        {
                            if (removeFks)
                            {
                                tableInfo.Key.ForeignKeyConstraints.Remove(fk);
                            }
                            else
                            {
                                fk.PrincipalTable = toTable;
                            }
                        }
                    }
                }
            }
        }
        public void GetEntityTypeMapping_should_return_mapping_for_type()
        {
            var databaseMapping = new DbDatabaseMapping()
                .Initialize(new EdmModel().Initialize(), new DbDatabaseMetadata());
            var entityType = new EdmEntityType();
            var entityTypeMapping = new DbEntityTypeMapping { EntityType = entityType };
            databaseMapping.AddEntitySetMapping(new EdmEntitySet()).EntityTypeMappings.Add(entityTypeMapping);

            Assert.Same(entityTypeMapping, databaseMapping.GetEntityTypeMapping(entityType));
        }
        private HashSet<EdmPropertyPath> DiscoverAllMappingsToContain(
            DbDatabaseMapping databaseMapping, EdmEntityType entityType, DbTableMetadata toTable,
            bool isSharingTableWithBase)
        {
            // Ensure all specified properties are the only ones present in this fragment and table
            var mappingsToContain = new HashSet<EdmPropertyPath>();

            // Include Key Properties always
            entityType.KeyProperties().Each(
                p =>
                mappingsToContain.AddRange(p.ToPropertyPathList()));

            // Include All Inherited Properties
            if (MapInheritedProperties)
            {
                entityType.Properties.Except(entityType.DeclaredProperties).Each(
                    p =>
                    mappingsToContain.AddRange(p.ToPropertyPathList()));
            }

            // If sharing table with base type, include all the mappings that the base has
            if (isSharingTableWithBase)
            {
                var baseMappingsToContain = new HashSet<EdmPropertyPath>();
                var baseType = entityType.BaseType;
                DbEntityTypeMapping baseMapping = null;
                DbEntityTypeMappingFragment baseFragment = null;
                // if the base is abstract it may have no mapping so look upwards until you find either:
                //   1. a type with mappings and 
                //   2. if none can be found (abstract until the root or hit another table), then include all declared properties on that base type
                while (baseType != null
                       && baseMapping == null)
                {
                    baseMapping = databaseMapping.GetEntityTypeMapping(entityType.BaseType);
                    if (baseMapping != null)
                    {
                        baseFragment = baseMapping.TypeMappingFragments.SingleOrDefault(tmf => tmf.Table == toTable);
                    }

                    if (baseFragment == null)
                    {
                        baseType.DeclaredProperties.Each(
                            p =>
                            baseMappingsToContain.AddRange(p.ToPropertyPathList()));
                    }

                    baseType = baseType.BaseType;
                }

                if (baseFragment != null)
                {
                    foreach (var pm in baseFragment.PropertyMappings)
                    {
                        mappingsToContain.Add(new EdmPropertyPath(pm.PropertyPath));
                    }
                }

                mappingsToContain.AddRange(baseMappingsToContain);
            }

            if (Properties == null)
            {
                // Include All Declared Properties
                entityType.DeclaredProperties.Each(
                    p =>
                    mappingsToContain.AddRange(p.ToPropertyPathList()));
            }
            else
            {
                // Include Specific Properties
                Properties.Each(
                    p =>
                    mappingsToContain.AddRange(PropertyPathToEdmPropertyPath(p, entityType)));
            }

            return mappingsToContain;
        }
        private DbEntityTypeMappingFragment FindOrCreateTypeMappingFragment(
            DbDatabaseMapping databaseMapping,
            ref DbEntityTypeMapping entityTypeMapping,
            int configurationIndex,
            EdmEntityType entityType,
            DbProviderManifest providerManifest)
        {
            DbEntityTypeMappingFragment fragment = null;

            if (entityTypeMapping == null)
            {
                Contract.Assert(entityType.IsAbstract);
                new EntityTypeMappingGenerator(providerManifest).
                    Generate(entityType, databaseMapping);
                entityTypeMapping = databaseMapping.GetEntityTypeMapping(entityType);
                configurationIndex = 0;
            }

            if (configurationIndex < entityTypeMapping.TypeMappingFragments.Count)
            {
                fragment = entityTypeMapping.TypeMappingFragments[configurationIndex];
            }
            else
            {
                if (MapInheritedProperties)
                {
                    throw Error.EntityMappingConfiguration_DuplicateMapInheritedProperties(entityType.Name);
                }
                else if (Properties == null)
                {
                    throw Error.EntityMappingConfiguration_DuplicateMappedProperties(entityType.Name);
                }
                else
                {
                    Properties.Each(
                        p =>
                            {
                                if (
                                    PropertyPathToEdmPropertyPath(p, entityType).Any(
                                        pp => !entityType.KeyProperties().Contains(pp.First())))
                                {
                                    throw Error.EntityMappingConfiguration_DuplicateMappedProperty(
                                        entityType.Name, p.ToString());
                                }
                            });
                }

                // Special case where they've asked for an extra table related to this type that only will include the PK columns
                // Uniquify: can be false, always move to a new table
                var templateTable = entityTypeMapping.TypeMappingFragments[0].Table;
                fragment = EntityMappingOperations.CreateTypeMappingFragment(
                    entityTypeMapping,
                    entityTypeMapping.TypeMappingFragments[0],
                    databaseMapping.Database.AddTable(templateTable.Name, templateTable));
            }
            return fragment;
        }
        private static DbTableMetadata FindBaseTableForExtraPropertyMapping(
            DbDatabaseMapping databaseMapping, EdmEntityType entityType, DbEdmPropertyMapping pm)
        {
            var baseType = entityType.BaseType;

            DbEntityTypeMappingFragment baseFragment = null;

            while (baseType != null
                   && baseFragment == null)
            {
                var baseMapping = databaseMapping.GetEntityTypeMapping(baseType);
                if (baseMapping != null)
                {
                    baseFragment =
                        baseMapping.TypeMappingFragments.SingleOrDefault(
                            f => f.PropertyMappings.Any(bpm => bpm.PropertyPath.SequenceEqual(pm.PropertyPath)));

                    if (baseFragment != null)
                    {
                        return baseFragment.Table;
                    }
                }
                baseType = baseType.BaseType;
            }
            return null;
        }
        private void ConfigureEntityTypes(DbDatabaseMapping databaseMapping, DbProviderManifest providerManifest)
        {
            var sortedEntityConfigurations =
                SortEntityConfigurationsByInheritance(databaseMapping);

            foreach (var entityTypeConfiguration in sortedEntityConfigurations)
            {
                var entityTypeMapping
                    = databaseMapping.GetEntityTypeMapping(entityTypeConfiguration.ClrType);

                entityTypeConfiguration.ConfigureTablesAndConditions(
                    entityTypeMapping, databaseMapping, providerManifest);

                // run through all unconfigured derived types of the current entityType to make sure the property mappings now point to the right places
                ConfigureUnconfiguredDerivedTypes(
                    databaseMapping,
                    providerManifest,
                    databaseMapping.Model.GetEntityType(entityTypeConfiguration.ClrType),
                    sortedEntityConfigurations);
            }

            new EntityMappingService(databaseMapping).Configure();

            foreach (var entityType in databaseMapping.Model.GetEntityTypes().Where(e => e.GetConfiguration() != null))
            {
                var entityTypeConfiguration = (EntityTypeConfiguration)entityType.GetConfiguration();

                entityTypeConfiguration.Configure(entityType, databaseMapping, providerManifest);
            }
        }
        protected static DbEntityTypeMapping GetEntityTypeMappingInHierarchy(
            DbDatabaseMapping databaseMapping, EdmEntityType entityType)
        {
            //Contract.Requires(databaseMapping != null);
            //Contract.Requires(entityType != null);

            var entityTypeMapping = databaseMapping.GetEntityTypeMapping(entityType);

            if (entityTypeMapping == null)
            {
                var entitySetMapping =
                    databaseMapping.GetEntitySetMapping(databaseMapping.Model.GetEntitySet(entityType));

                if (entitySetMapping != null)
                {
                    entityTypeMapping = entitySetMapping
                        .EntityTypeMappings
                        .First(
                            etm => entityType.DeclaredProperties.All(
                                dp => etm.TypeMappingFragments.First()
                                          .PropertyMappings.Select(pm => pm.PropertyPath.First()).Contains(dp)));
                }
            }

            if (entityTypeMapping == null)
            {
                throw Error.UnmappedAbstractType(entityType.GetClrType());
            }

            return entityTypeMapping;
        }