示例#1
0
        /// <summary>
        ///     Adds a new relationship to this entity.
        /// </summary>
        /// <param name="properties"> The properties that the foreign key is defined on. </param>
        /// <param name="principalKey"> The primary or alternate key that is referenced. </param>
        /// <param name="principalEntity">
        ///     The entity type that the relationship targets. This may be different from the type that <paramref name="principalKey" />
        ///     is defined on when the relationship targets a derived type in an inheritance hierarchy (since the key is defined on the
        ///     base type of the hierarchy).
        /// </param>
        /// <returns> The newly created foreign key. </returns>
        internal ForeignKey AddForeignKey(IReadOnlyList <Property> properties, Key principalKey, Entity principalEntity, bool runConventions = true)
        {
            Check.NotEmpty(properties, nameof(properties));
            Check.HasNoNulls(properties, nameof(properties));
            Check.NotNull(principalKey, nameof(principalKey));
            Check.NotNull(principalEntity, nameof(principalEntity));

            foreach (var property in properties)
            {
                var actualProperty = FindProperty(property.Name);
                if (actualProperty == null || !actualProperty.DeclaringEntity.IsAssignableFrom(property.DeclaringEntity))
                {
                    throw new InvalidOperationException(ResX.ForeignKeyPropertiesWrongEntity(Property.Format(properties), Name));
                }

                if (actualProperty.GetContainingKeys().Any(k => k.DeclaringEntity != this))
                {
                    throw new InvalidOperationException(ResX.ForeignKeyPropertyInKey(actualProperty.Name, Name));
                }
            }

            var duplicateForeignKey = FindForeignKeysInHierarchy(properties, principalKey, principalEntity).FirstOrDefault();

            if (duplicateForeignKey != null)
            {
                throw new InvalidOperationException(ResX.DuplicateForeignKey(Property.Format(properties), Name, duplicateForeignKey.DeclaringEntity.Name, Property.Format(principalKey.Properties), principalEntity.Name));
            }

            var foreignKey = new ForeignKey(properties, principalKey, this, principalEntity);

            _foreignKeys.Add(foreignKey);

            foreach (var property in properties)
            {
                var currentKeys = property.ForeignKeys;
                if (currentKeys == null)
                {
                    property.ForeignKeys = new ForeignKey[] { foreignKey };
                }
                else
                {
                    var newKeys = currentKeys.ToList();
                    newKeys.Add(foreignKey);
                    property.ForeignKeys = newKeys;
                }
            }

            if (principalKey.ReferencingForeignKeys == null)
            {
                principalKey.ReferencingForeignKeys = new List <ForeignKey> {
                    foreignKey
                };
            }
            else
            {
                principalKey.ReferencingForeignKeys.Add(foreignKey);
            }

            if (principalEntity.DeclaredReferencingForeignKeys == null)
            {
                principalEntity.DeclaredReferencingForeignKeys = new List <ForeignKey> {
                    foreignKey
                };
            }
            else
            {
                principalEntity.DeclaredReferencingForeignKeys.Add(foreignKey);
            }

            if (runConventions)
            {
                Model.ConventionDispatcher.OnForeignKeyAdded(foreignKey);
            }

            return(foreignKey);
        }
示例#2
0
        public Navigation(PropertyInfo navigationProperty, ForeignKey fkToLinkedEntity, ForeignKey fkToTargetedEntity) : base(Check.NotNull(navigationProperty, nameof(navigationProperty)).Name, navigationProperty)
        {
            Check.NotNull(fkToLinkedEntity, nameof(fkToLinkedEntity));
            Check.NotNull(fkToTargetedEntity, nameof(fkToTargetedEntity));

            ForeignKeyToLinkedEntity   = fkToLinkedEntity;
            ForeignKeyToTargetedEntity = fkToTargetedEntity;
        }
示例#3
0
        internal Navigation AddNavigation(PropertyInfo navigationProperty, ForeignKey fkToLinkedEntity, ForeignKey fkToTargetedEntity)
        {
            Check.NotNull(navigationProperty, nameof(navigationProperty));
            Check.NotNull(fkToLinkedEntity, nameof(fkToLinkedEntity));
            Check.NotNull(fkToTargetedEntity, nameof(fkToTargetedEntity));

            var name = navigationProperty.Name;
            var duplicateNavigation = FindNavigationsInHierarchy(name).FirstOrDefault();

            if (duplicateNavigation != null)
            {
                throw new InvalidOperationException(ResX.DuplicateNavigation(name, Name, duplicateNavigation.DeclaringEntity.Name));
            }

            var duplicateProperty = FindPropertiesInHierarchy(name).FirstOrDefault();

            if (duplicateProperty != null)
            {
                throw new InvalidOperationException(ResX.ConflictingProperty(name, Name, duplicateProperty.DeclaringEntity.Name));
            }

            var navigation = new Navigation(navigationProperty, fkToLinkedEntity, fkToTargetedEntity);

            _navigations.Add(name, navigation);

            return(navigation);
        }
 /// <summary>
 ///     Gets the relational database specific metadata for a foreign key.
 /// </summary>
 /// <param name="foreignKey"> The foreign key to get metadata for. </param>
 /// <returns> The relational database specific metadata for the foreign key. </returns>
 public static IRelationalForeignKeyAnnotations Relational(this ForeignKey foreignKey)
 => new RelationalForeignKeyAnnotations(Check.NotNull(foreignKey, nameof(foreignKey)));