예제 #1
0
        public virtual InternalRelationshipBuilder Relationship(
            [NotNull] InternalEntityBuilder principalEntityTypeBuilder,
            [NotNull] InternalEntityBuilder dependentEntityTypeBuilder,
            [CanBeNull] string navigationToPrincipalName,
            [CanBeNull] string navigationToDependentName,
            ConfigurationSource configurationSource,
            bool?oneToOne        = null,
            bool strictPrincipal = true)
        {
            Check.NotNull(principalEntityTypeBuilder, "principalEntityTypeBuilder");
            Check.NotNull(dependentEntityTypeBuilder, "dependentEntityTypeBuilder");

            if (dependentEntityTypeBuilder != this)
            {
                return(dependentEntityTypeBuilder.Relationship(
                           principalEntityTypeBuilder,
                           dependentEntityTypeBuilder,
                           navigationToPrincipalName,
                           navigationToDependentName,
                           configurationSource,
                           oneToOne,
                           strictPrincipal));
            }

            if (!string.IsNullOrEmpty(navigationToPrincipalName) &&
                !dependentEntityTypeBuilder.CanAdd(navigationToPrincipalName, isNavigation: true, configurationSource: configurationSource))
            {
                return(null);
            }

            if (!string.IsNullOrEmpty(navigationToDependentName) &&
                !principalEntityTypeBuilder.CanAdd(navigationToDependentName, isNavigation: true, configurationSource: configurationSource))
            {
                return(null);
            }

            var principalEntityType = principalEntityTypeBuilder.Metadata;
            var dependentEntityType = dependentEntityTypeBuilder.Metadata;

            if (principalEntityType.TryGetPrimaryKey() == null)
            {
                if (configurationSource == ConfigurationSource.Explicit)
                {
                    throw new InvalidOperationException(Strings.PrincipalEntityTypeRequiresKey(principalEntityType.Name));
                }

                return(null);
            }

            var navigationToPrincipal = string.IsNullOrEmpty(navigationToPrincipalName)
                ? null
                : dependentEntityType.TryGetNavigation(navigationToPrincipalName);

            if (navigationToPrincipal != null &&
                navigationToPrincipal.IsCompatible(principalEntityType, dependentEntityType, strictPrincipal ? (bool?)true : null, oneToOne))
            {
                return(Relationship(navigationToPrincipal, configurationSource, navigationToDependentName));
            }

            var navigationToDependent = string.IsNullOrEmpty(navigationToDependentName)
                ? null
                : principalEntityType.TryGetNavigation(navigationToDependentName);

            if (navigationToDependent != null &&
                navigationToDependent.IsCompatible(principalEntityType, dependentEntityType, strictPrincipal? (bool?)false : null, oneToOne))
            {
                return(Relationship(navigationToDependent, configurationSource, navigationToPrincipalName));
            }

            if (!RemoveRelationships(configurationSource, navigationToPrincipal?.ForeignKey, navigationToDependent?.ForeignKey))
            {
                return(null);
            }

            navigationToPrincipalName = navigationToPrincipalName == "" ? null : navigationToPrincipalName;
            navigationToDependentName = navigationToDependentName == "" ? null : navigationToDependentName;

            var foreignKey = new ForeignKeyConvention()
                             .CreateForeignKeyByConvention(
                principalEntityType,
                dependentEntityType,
                navigationToPrincipalName,
                null,
                null,
                oneToOne);

            if (foreignKey == null)
            {
                return(null);
            }

            var relationshipBuilder = new InternalRelationshipBuilder(foreignKey, dependentEntityTypeBuilder.ModelBuilder, foreignKeyConfigurationSource: null);

            Debug.Assert(relationshipBuilder.Metadata.EntityType == Metadata);

            _relationshipBuilders.Value.Add(foreignKey, relationshipBuilder, configurationSource);

            if (navigationToPrincipalName != null)
            {
                var navigationToPrincipalSet = dependentEntityTypeBuilder
                                               .Navigation(navigationToPrincipalName, foreignKey, pointsToPrincipal: true, configurationSource: configurationSource);
                Debug.Assert(navigationToPrincipalSet);
            }

            if (navigationToDependentName != null)
            {
                var navigationToDependentSet = principalEntityTypeBuilder
                                               .Navigation(navigationToDependentName, foreignKey, pointsToPrincipal: false, configurationSource: configurationSource);
                Debug.Assert(navigationToDependentSet);
            }

            return(relationshipBuilder);
        }
예제 #2
0
 public static RelationalForeignKeyBuilderAnnotations SqlServer(
     [NotNull] this InternalRelationshipBuilder builder,
     ConfigurationSource configurationSource)
 => new RelationalForeignKeyBuilderAnnotations(builder, configurationSource, SqlServerAnnotationNames.Prefix);
        public virtual InternalRelationshipBuilder ReplaceForeignKey(
            [NotNull] InternalRelationshipBuilder relationshipBuilder,
            [NotNull] IReadOnlyList <Property> dependentProperties,
            [NotNull] IReadOnlyList <Property> principalProperties,
            ConfigurationSource configurationSource)
        {
            if (!_relationshipBuilders.Value.Remove(relationshipBuilder.Metadata, configurationSource))
            {
                return(null);
            }

            // TODO: avoid removing and readding the navigation property
            if (relationshipBuilder.NavigationToPrincipal != null)
            {
                relationshipBuilder.DependentType.RemoveNavigation(relationshipBuilder.NavigationToPrincipal);
            }

            if (relationshipBuilder.NavigationToDependent != null)
            {
                relationshipBuilder.PrincipalType.RemoveNavigation(relationshipBuilder.NavigationToDependent);
            }

            var entityType = relationshipBuilder.Metadata.EntityType;

            // TODO: Remove FK only if it was added by convention
            // Issue #213
            entityType.RemoveForeignKey(relationshipBuilder.Metadata);

            var newForeignKey = new ForeignKeyConvention().FindOrCreateForeignKey(
                relationshipBuilder.PrincipalType,
                relationshipBuilder.DependentType,
                relationshipBuilder.NavigationToPrincipal != null ? relationshipBuilder.NavigationToPrincipal.Name : null,
                relationshipBuilder.NavigationToDependent != null ? relationshipBuilder.NavigationToDependent.Name : null,
                dependentProperties,
                principalProperties,
                ((IForeignKey)relationshipBuilder.Metadata).IsUnique);

            // TODO: Remove principal key only if it was added by convention
            // Issue #213
            var currentPrincipalKey = relationshipBuilder.Metadata.ReferencedKey;

            if (currentPrincipalKey != newForeignKey.ReferencedKey &&
                currentPrincipalKey != currentPrincipalKey.EntityType.TryGetPrimaryKey() &&
                currentPrincipalKey.Properties.All(p => p.IsShadowProperty))
            {
                currentPrincipalKey.EntityType.RemoveKey(currentPrincipalKey);
            }

            var propertiesInUse = entityType.Keys.SelectMany(k => k.Properties)
                                  .Concat(entityType.ForeignKeys.SelectMany(k => k.Properties))
                                  .Concat(relationshipBuilder.Metadata.ReferencedEntityType.Keys.SelectMany(k => k.Properties))
                                  .Concat(relationshipBuilder.Metadata.ReferencedEntityType.ForeignKeys.SelectMany(k => k.Properties))
                                  .Concat(dependentProperties)
                                  .Concat(principalProperties)
                                  .Where(p => p.IsShadowProperty)
                                  .Distinct();

            var propertiesToRemove = Metadata.Properties
                                     .Concat(relationshipBuilder.Metadata.ReferencedKey.Properties)
                                     .Where(p => p.IsShadowProperty)
                                     .Distinct()
                                     .Except(propertiesInUse)
                                     .ToList();

            // TODO: Remove property only if it was added by convention
            // Issue #213
            foreach (var property in propertiesToRemove)
            {
                property.EntityType.RemoveProperty(property);
            }

            var navigationToPrincipal = relationshipBuilder.NavigationToPrincipal;

            if (navigationToPrincipal != null)
            {
                navigationToPrincipal = relationshipBuilder.DependentType.AddNavigation(
                    navigationToPrincipal.Name, newForeignKey, navigationToPrincipal.PointsToPrincipal);
            }

            var navigationToDependent = relationshipBuilder.NavigationToDependent;

            if (navigationToDependent != null)
            {
                navigationToDependent = relationshipBuilder.PrincipalType.AddNavigation(
                    navigationToDependent.Name, newForeignKey, navigationToDependent.PointsToPrincipal);
            }

            var owner = this;

            if (Metadata != newForeignKey.EntityType)
            {
                owner = ModelBuilder.Entity(newForeignKey.EntityType.Name, configurationSource);
            }

            var builder = owner._relationshipBuilders.Value.TryGetValue(newForeignKey, configurationSource);

            if (builder != null)
            {
                if (builder.PrincipalType == relationshipBuilder.PrincipalType &&
                    builder.DependentType == relationshipBuilder.DependentType &&
                    builder.NavigationToPrincipal == navigationToPrincipal &&
                    builder.NavigationToDependent == navigationToDependent)
                {
                    return(builder);
                }

                if (!owner._relationshipBuilders.Value.Remove(newForeignKey, configurationSource))
                {
                    return(null);
                }
            }

            builder = new InternalRelationshipBuilder(
                relationshipBuilder,
                newForeignKey,
                navigationToPrincipal,
                navigationToDependent);
            owner._relationshipBuilders.Value.Add(newForeignKey, builder, configurationSource);
            return(builder);
        }
 public static RelationalForeignKeyBuilderAnnotations Relational(
     [NotNull] this InternalRelationshipBuilder builder,
     ConfigurationSource configurationSource)
 => new RelationalForeignKeyBuilderAnnotations(builder, configurationSource, null);