예제 #1
0
        private static bool IsAssociatedWithEntityType(this AssociationType association, EntityType entityType)
        {
            var end1 = association.GetEnd1();
            AssociationEndMember end2 = association.GetEnd2();

            return(end1.GetEntityType() == entityType || end2.GetEntityType() == entityType);
        }
예제 #2
0
        internal static XElement ConstructReferentialConstraint(
            string principalRole, AssociationEndMember principalEnd,
            string dependentRole, AssociationEndMember dependentEnd)
        {
            var refConstraintElement = new XElement(_ssdl + "ReferentialConstraint");

            if (dependentEnd != null &&
                principalEnd != null)
            {
                var dependentEntityType = dependentEnd.GetEntityType();
                var principalEntityType = principalEnd.GetEntityType();
                if (dependentEntityType != null &&
                    principalEntityType != null)
                {
                    refConstraintElement = ConstructReferentialConstraintInternal(
                        principalRole,
                        principalEntityType.GetKeyProperties().Select(k => k.Name),
                        dependentRole,
                        principalEntityType.GetKeyProperties().Select(
                            k => OutputGeneratorHelpers.GetFkName(
                                dependentEnd.DeclaringType as AssociationType,
                                dependentEnd,
                                k.Name)));
                }
            }

            return(refConstraintElement);
        }
        /// <inheritdoc/>
        protected override bool MatchDependentKeyProperty(
            AssociationType associationType,
            AssociationEndMember dependentAssociationEnd,
            EdmProperty dependentProperty,
            EntityType principalEntityType,
            EdmProperty principalKeyProperty)
        {
            Check.NotNull(associationType, "associationType");
            Check.NotNull(dependentAssociationEnd, "dependentAssociationEnd");
            Check.NotNull(dependentProperty, "dependentProperty");
            Check.NotNull(principalEntityType, "principalEntityType");
            Check.NotNull(principalKeyProperty, "principalKeyProperty");

            var otherEnd = associationType.GetOtherEnd(dependentAssociationEnd);

            var navigationProperty
                = dependentAssociationEnd.GetEntityType().NavigationProperties
                  .SingleOrDefault(n => n.ResultEnd == otherEnd);

            if (navigationProperty == null)
            {
                return(false);
            }

            return(string.Equals(
                       dependentProperty.Name, navigationProperty.Name + principalKeyProperty.Name,
                       StringComparison.OrdinalIgnoreCase));
        }
예제 #4
0
        // <summary>
        //     1. If there is a NavigationProperty on the dependent end, then the FK name will be: [NavProp Name]_[Property Name]
        //     2. If there isn't a NavigationProperty, then we will use the [Association Name]_[EndName]_[Property Name]
        // </summary>
        internal static string GetFkName(AssociationType association, AssociationEndMember endWithNavProp, string keyPropertyName)
        {
            var fkName = String.Empty;

            // We attempt to find a navigation property that uses the same association and points to the other end. That last
            // part is important with self-associations.
            var principalEnd       = association.GetOtherEnd(endWithNavProp);
            var navigationProperty = endWithNavProp
                                     .GetEntityType()
                                     .NavigationProperties
                                     .Where(np => (np.RelationshipType == association && np.ToEndMember == principalEnd)).FirstOrDefault();

            if (navigationProperty != null)
            {
                // First attempt to find the NavigationProperty that points to the principal end
                fkName = String.Format(CultureInfo.CurrentCulture, "{0}_{1}", navigationProperty.Name, keyPropertyName);
            }
            else if (association != null)
            {
                // If there isn't a NavigationProperty defined, then we will use the Association Name
                fkName = String.Format(CultureInfo.CurrentCulture, "{0}_{1}_{2}", association.Name, endWithNavProp.Name, keyPropertyName);
            }

            Debug.Assert(!String.IsNullOrEmpty(fkName), "Foreign key name could not be determined for the association " + association.Name);
            //fkName = GetTablePrefix(association.GetEnd1().GetEntityType().NamespaceName) + fkName;
            return(fkName);
        }
예제 #5
0
        private static IEnumerable <AssociationType> FindAllOneToOneFKAssociationTypes(
            EdmModel model,
            EntityType entityType,
            EntityType candidateType)
        {
            List <AssociationType> associationTypeList = new List <AssociationType>();

            foreach (EntityContainer container in model.Containers)
            {
                ReadOnlyMetadataCollection <AssociationSet> associationSets = container.AssociationSets;
                for (int index = 0; index < associationSets.Count; ++index)
                {
                    AssociationSet       associationSet = associationSets[index];
                    AssociationEndMember sourceEnd      = associationSet.ElementType.SourceEnd;
                    AssociationEndMember targetEnd      = associationSet.ElementType.TargetEnd;
                    EntityType           entityType1    = sourceEnd.GetEntityType();
                    EntityType           entityType2    = targetEnd.GetEntityType();
                    if (associationSet.ElementType.Constraint != null && sourceEnd.RelationshipMultiplicity == RelationshipMultiplicity.One && targetEnd.RelationshipMultiplicity == RelationshipMultiplicity.One && (entityType1 == entityType && entityType2 == candidateType || entityType2 == entityType && entityType1 == candidateType))
                    {
                        associationTypeList.Add(associationSet.ElementType);
                    }
                }
            }
            return((IEnumerable <AssociationType>)associationTypeList);
        }
예제 #6
0
        public static IEnumerable <EdmProperty> GetKeyProperties(this AssociationEndMember end)
        {
            IEnumerable <EdmProperty> keyProperties = new List <EdmProperty>();
            var entityType = end.GetEntityType();

            if (entityType != null)
            {
                keyProperties = entityType.GetKeyProperties();
            }
            return(keyProperties);
        }
예제 #7
0
        // TODO: in order to properly identify this we may need to add custom annotations in the SSDL
        /// <summary>
        ///     We can infer that something is a join table in the SSDL if:
        ///     1. There are two associations originating from it
        ///     2. The two ends on the table are *
        ///     3. The other ends on the associations are 1
        ///     4. The number of properties in the table is equal to the sum of all the key properties on the other ends of both associations
        ///     5. All properties in the table are key properties
        /// </summary>
        /// <param name="entityType">The EntityType to test.</param>
        /// <param name="store">The StoreItemCollection containing EntityType.</param>
        /// <returns>true if the specified EntityType is a join table; otherwise, false.</returns>
        public static bool IsJoinTable(this EntityType entityType, StoreItemCollection store)
        {
            var associations = store.GetAllAssociations().Where(a => a.IsAssociatedWithEntityType(entityType));

            if (associations.Count() == 2)
            {
                var sumOfAllKeyProperties      = 0;
                var numEndsWithOneMultiplicity = 0;
                foreach (AssociationType association in associations)
                {
                    AssociationEndMember end1 = association.GetEnd1();
                    AssociationEndMember end2 = association.GetEnd2();
                    if ((end1.GetEntityType() == entityType) &&
                        (end1.RelationshipMultiplicity == RelationshipMultiplicity.Many) &&
                        (end2.RelationshipMultiplicity == RelationshipMultiplicity.One))
                    {
                        sumOfAllKeyProperties += end2.GetEntityType().GetKeyProperties().Count();
                        numEndsWithOneMultiplicity++;
                    }
                    else if ((end2.GetEntityType() == entityType) &&
                             (end2.RelationshipMultiplicity == RelationshipMultiplicity.Many) &&
                             (end1.RelationshipMultiplicity == RelationshipMultiplicity.One))
                    {
                        sumOfAllKeyProperties += end1.GetEntityType().GetKeyProperties().Count();
                        numEndsWithOneMultiplicity++;
                    }
                }

                int intersectCount = entityType.GetKeyProperties().Intersect(entityType.Properties).Count();

                if (numEndsWithOneMultiplicity == 2 &&
                    entityType.GetKeyProperties().Count() == sumOfAllKeyProperties &&
                    entityType.GetKeyProperties().Count() == intersectCount &&
                    entityType.Properties.Count == intersectCount)
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #8
0
        internal void WriteAssociationEndElementHeader(AssociationEndMember associationEnd)
        {
            _xmlWriter.WriteStartElement(XmlConstants.End);
            _xmlWriter.WriteAttributeString(XmlConstants.Role, associationEnd.Name);

            var typeName = associationEnd.GetEntityType().Name;

            _xmlWriter.WriteAttributeString(
                XmlConstants.TypeAttribute, GetQualifiedTypeName(XmlConstants.Self, typeName));
            _xmlWriter.WriteAttributeString(
                XmlConstants.Multiplicity, GetXmlMultiplicity(associationEnd.RelationshipMultiplicity));
        }
예제 #9
0
        // <summary>
        //     A name derived from a *:* association will be: FK_[Association Name]_[End Name]. Note that we are
        //     getting the association name for *one* of the SSDL associations that are inferred from a CSDL *:*
        //     association. The 'principalEnd' corresponds to the end of the *:* association that will become
        //     the principal end in the 1:* association (where the * end is the newly-constructed entity corresponding
        //     to the link table)
        // </summary>
        internal static string GetStorageAssociationSetNameFromManyToMany(AssociationSet associationSet, AssociationEndMember principalEnd)
        {
            Debug.Assert(associationSet != null, "AssociationSet should not be null");
            Debug.Assert(principalEnd != null, "The principal end cannot be null");
            var associationSetName = String.Empty;

            if (associationSet != null &&
                principalEnd != null)
            {
                associationSetName = String.Format(
                    CultureInfo.CurrentCulture, Resources.CodeViewManyToManyAssocName,
                    OutputGeneratorHelpers.GetTablePrefix(principalEnd.GetEntityType().NamespaceName) + associationSet.Name,
                    principalEnd.Name);
            }
            return(associationSetName);
        }
예제 #10
0
 /// <inheritdoc />
 protected override bool MatchDependentKeyProperty(
   AssociationType associationType,
   AssociationEndMember dependentAssociationEnd,
   EdmProperty dependentProperty,
   EntityType principalEntityType,
   EdmProperty principalKeyProperty)
 {
   Check.NotNull<AssociationType>(associationType, nameof (associationType));
   Check.NotNull<AssociationEndMember>(dependentAssociationEnd, nameof (dependentAssociationEnd));
   Check.NotNull<EdmProperty>(dependentProperty, nameof (dependentProperty));
   Check.NotNull<EntityType>(principalEntityType, nameof (principalEntityType));
   Check.NotNull<EdmProperty>(principalKeyProperty, nameof (principalKeyProperty));
   AssociationEndMember otherEnd = associationType.GetOtherEnd(dependentAssociationEnd);
   NavigationProperty navigationProperty = dependentAssociationEnd.GetEntityType().NavigationProperties.SingleOrDefault<NavigationProperty>((Func<NavigationProperty, bool>) (n => n.ResultEnd == otherEnd));
   if (navigationProperty == null)
     return false;
   return string.Equals(dependentProperty.Name, navigationProperty.Name + principalKeyProperty.Name, StringComparison.OrdinalIgnoreCase);
 }
예제 #11
0
        // <summary>
        //     A name derived from a *:* association will be: FK_[Association Name]_[End Name]. Note that we are
        //     getting the association name for *one* of the SSDL associations that are inferred from a CSDL *:*
        //     association. The 'principalEnd' corresponds to the end of the *:* association that will become
        //     the principal end in the 1:* association (where the * end is the newly-constructed entity corresponding
        //     to the link table)
        // </summary>
        internal static string GetStorageAssociationNameFromManyToMany(AssociationEndMember principalEnd)
        {
            var association = principalEnd.DeclaringType as AssociationType;

            Debug.Assert(
                association != null, "The DeclaringType of the AssociationEndMember " + principalEnd.Name + " should be an AssociationType");
            Debug.Assert(principalEnd != null, "The principal end cannot be null");
            var associationName = String.Empty;

            if (association != null &&
                principalEnd != null)
            {
                associationName = String.Format(
                    CultureInfo.CurrentCulture, Resources.CodeViewManyToManyAssocName,
                    OutputGeneratorHelpers.GetTablePrefix(principalEnd.GetEntityType().NamespaceName) + association.Name,
                    principalEnd.Name);
            }
            return(associationName);
        }
예제 #12
0
        /// <inheritdoc />
        public virtual void Apply(NavigationProperty item, DbModel model)
        {
            Check.NotNull <NavigationProperty>(item, nameof(item));
            Check.NotNull <DbModel>(model, nameof(model));
            AssociationType association = item.Association;

            if (association.Constraint != null)
            {
                return;
            }
            ForeignKeyAttribute  foreignKeyAttribute = item.GetClrAttributes <ForeignKeyAttribute>().SingleOrDefault <ForeignKeyAttribute>();
            AssociationEndMember principalEnd;
            AssociationEndMember dependentEnd;

            if (foreignKeyAttribute == null || !association.TryGuessPrincipalAndDependentEnds(out principalEnd, out dependentEnd) && !association.IsPrincipalConfigured())
            {
                return;
            }
            AssociationEndMember associationEndMember = dependentEnd ?? association.TargetEnd;

            principalEnd = principalEnd ?? association.SourceEnd;
            IEnumerable <string>      dependentPropertyNames = ((IEnumerable <string>)foreignKeyAttribute.Name.Split(',')).Select <string, string>((Func <string, string>)(p => p.Trim()));
            EntityType                declaringEntityType    = model.ConceptualModel.EntityTypes.Single <EntityType>((Func <EntityType, bool>)(e => e.DeclaredNavigationProperties.Contains(item)));
            List <EdmProperty>        list       = ForeignKeyNavigationPropertyAttributeConvention.GetDependentProperties(associationEndMember.GetEntityType(), dependentPropertyNames, declaringEntityType, item).ToList <EdmProperty>();
            ReferentialConstraint     constraint = new ReferentialConstraint((RelationshipEndMember)principalEnd, (RelationshipEndMember)associationEndMember, (IEnumerable <EdmProperty>)principalEnd.GetEntityType().KeyProperties().ToList <EdmProperty>(), (IEnumerable <EdmProperty>)list);
            IEnumerable <EdmProperty> source     = associationEndMember.GetEntityType().KeyProperties();

            if (source.Count <EdmProperty>() == constraint.ToProperties.Count <EdmProperty>() && source.All <EdmProperty>((Func <EdmProperty, bool>)(kp => constraint.ToProperties.Contains(kp))))
            {
                principalEnd.RelationshipMultiplicity = RelationshipMultiplicity.One;
                if (associationEndMember.RelationshipMultiplicity.IsMany())
                {
                    associationEndMember.RelationshipMultiplicity = RelationshipMultiplicity.ZeroOrOne;
                }
            }
            if (principalEnd.IsRequired())
            {
                constraint.ToProperties.Each <EdmProperty, bool>((Func <EdmProperty, bool>)(p => p.Nullable = false));
            }
            association.Constraint = constraint;
        }
예제 #13
0
        internal override void Configure(
            AssociationType associationType,
            AssociationEndMember dependentEnd,
            EntityTypeConfiguration entityTypeConfiguration)
        {
            DebugCheck.NotNull(associationType);
            DebugCheck.NotNull(dependentEnd);
            DebugCheck.NotNull(entityTypeConfiguration);

            if (!_dependentProperties.Any())
            {
                return;
            }

            var dependentPropertInfos = _dependentProperties.AsEnumerable();

            if (!IsFullySpecified)
            {
                var foreignKeys
                    = from p in _dependentProperties
                      select new
                    {
                    PropertyInfo = p,
                    entityTypeConfiguration.Property(new PropertyPath(p)).ColumnOrder
                    };

                if ((_dependentProperties.Count > 1) &&
                    foreignKeys.Any(p => !p.ColumnOrder.HasValue))
                {
                    var dependentKeys = dependentEnd.GetEntityType().KeyProperties;

                    if ((dependentKeys.Count == _dependentProperties.Count) &&
                        foreignKeys.All(fk => dependentKeys.Any(p => p.GetClrPropertyInfo().IsSameAs(fk.PropertyInfo))))
                    {
                        // The FK and PK sets are equal, we know the order
                        dependentPropertInfos = dependentKeys.Select(p => p.GetClrPropertyInfo());
                    }
                    else
                    {
                        throw Error.ForeignKeyAttributeConvention_OrderRequired(entityTypeConfiguration.ClrType);
                    }
                }
                else
                {
                    dependentPropertInfos = foreignKeys.OrderBy(p => p.ColumnOrder).Select(p => p.PropertyInfo);
                }
            }

            var dependentProperties = new List <EdmProperty>();

            foreach (var dependentProperty in dependentPropertInfos)
            {
                var property
                    = dependentEnd.GetEntityType()
                      .GetDeclaredPrimitiveProperty(dependentProperty);

                if (property == null)
                {
                    throw Error.ForeignKeyPropertyNotFound(
                              dependentProperty.Name, dependentEnd.GetEntityType().Name);
                }

                dependentProperties.Add(property);
            }

            var principalEnd = associationType.GetOtherEnd(dependentEnd);

            var associationConstraint
                = new ReferentialConstraint(
                      principalEnd,
                      dependentEnd,
                      principalEnd.GetEntityType().KeyProperties,
                      dependentProperties);

            if (principalEnd.IsRequired())
            {
                associationConstraint.ToProperties.Each(p => p.Nullable = false);
            }

            associationType.Constraint = associationConstraint;
        }
예제 #14
0
        /// <inheritdoc />
        public virtual void Apply(AssociationType item, DbModel model)
        {
            Check.NotNull <AssociationType>(item, nameof(item));
            Check.NotNull <DbModel>(model, nameof(model));
            if (!item.IsOneToOne() || item.IsSelfReferencing() || (item.IsIndependent() || item.Constraint != null))
            {
                return;
            }
            IEnumerable <EdmProperty> source1 = item.SourceEnd.GetEntityType().KeyProperties();
            IEnumerable <EdmProperty> source2 = item.TargetEnd.GetEntityType().KeyProperties();
            AssociationEndMember      principalEnd;
            AssociationEndMember      dependentEnd;

            if (source1.Count <EdmProperty>() != source2.Count <EdmProperty>() || (!source1.Select <EdmProperty, PrimitiveType>((Func <EdmProperty, PrimitiveType>)(p => p.UnderlyingPrimitiveType)).SequenceEqual <PrimitiveType>(source2.Select <EdmProperty, PrimitiveType>((Func <EdmProperty, PrimitiveType>)(p => p.UnderlyingPrimitiveType))) || !item.TryGuessPrincipalAndDependentEnds(out principalEnd, out dependentEnd) && !item.IsPrincipalConfigured()))
            {
                return;
            }
            AssociationEndMember  associationEnd        = dependentEnd ?? item.TargetEnd;
            AssociationEndMember  otherEnd              = item.GetOtherEnd(associationEnd);
            ReferentialConstraint referentialConstraint = new ReferentialConstraint((RelationshipEndMember)otherEnd, (RelationshipEndMember)associationEnd, (IEnumerable <EdmProperty>)otherEnd.GetEntityType().KeyProperties().ToList <EdmProperty>(), (IEnumerable <EdmProperty>)associationEnd.GetEntityType().KeyProperties().ToList <EdmProperty>());

            item.Constraint = referentialConstraint;
        }
예제 #15
0
 private static NavigationProperty GetNavigationProperty(AssociationEndMember member)
 {
     return(member.GetEntityType().NavigationProperties.SingleOrDefault(property => property.RelationshipType == member.DeclaringType && property.FromEndMember == member));
 }
예제 #16
0
        private List <ModelBidirectionalAssociation> GetBidirectionalAssociations(EntityType entityType)
        {
            List <ModelBidirectionalAssociation> result = new List <ModelBidirectionalAssociation>();

            if (entityType == null)
            {
                return(result);
            }

            foreach (NavigationProperty navigationProperty in entityType.DeclaredNavigationProperties.Where(np => Inverse(np) != null))
            {
                StructuralType sourceType = navigationProperty.DeclaringType;

                if (sourceType.Name != entityType.Name)
                {
                    continue;
                }

                ModelBidirectionalAssociation association = new ModelBidirectionalAssociation();
                EntityType targetType = navigationProperty.ToEndMember.GetEntityType();

                AssociationType       associationType = navigationProperty.RelationshipType as AssociationType;
                ReferentialConstraint constraint      = associationType?.Constraint;
                AssociationEndMember  principalEnd    = constraint?.FromRole as AssociationEndMember;
                EntityType            principalType   = principalEnd?.GetEntityType();

                AssociationEndMember dependentEnd  = constraint?.ToRole as AssociationEndMember;
                EntityType           dependentType = dependentEnd?.GetEntityType();

                if (principalType?.Name == sourceType.Name)
                {
                    association.SourceRole = AssociationRole.Principal;
                    association.TargetRole = AssociationRole.Dependent;
                }
                else if (principalType?.Name == targetType.Name)
                {
                    association.TargetRole = AssociationRole.Principal;
                    association.SourceRole = AssociationRole.Dependent;
                }
                else if (principalType == null && dependentType == null)
                {
                    association.SourceRole = AssociationRole.NotApplicable;
                    association.TargetRole = AssociationRole.NotApplicable;
                }

                association.SourceClassName      = sourceType.Name;
                association.SourceClassNamespace = sourceType.NamespaceName;
                association.TargetClassName      = targetType.Name;
                association.TargetClassNamespace = targetType.NamespaceName;

                NavigationProperty inverse = Inverse(navigationProperty);

                // the property in the source class (referencing the target class)
                association.TargetPropertyTypeName = targetType.Name;
                association.TargetPropertyName     = navigationProperty.Name;
                association.TargetMultiplicity     = ConvertMultiplicity(navigationProperty.ToEndMember.RelationshipMultiplicity);
                association.TargetSummary          = navigationProperty.ToEndMember.Documentation?.Summary;
                association.TargetDescription      = navigationProperty.ToEndMember.Documentation?.LongDescription;

                // the property in the target class (referencing the source class)
                association.SourcePropertyTypeName = navigationProperty.FromEndMember.GetEntityType().Name;
                association.SourcePropertyName     = inverse?.Name;
                association.SourceMultiplicity     = ConvertMultiplicity(navigationProperty.FromEndMember.RelationshipMultiplicity);
                association.SourceSummary          = navigationProperty.FromEndMember.Documentation?.Summary;
                association.SourceDescription      = navigationProperty.FromEndMember.Documentation?.LongDescription;

                // look for declared foreign keys
                List <EdmProperty> dependentProperties = navigationProperty.GetDependentProperties().ToList();

                if (dependentProperties.Any())
                {
                    association.ForeignKey = string.Join(",", dependentProperties.Select(p => p.Name));
                }

                log.Debug($"Found bidirectional association {association.SourceClassName}.{association.TargetPropertyName} <-> {association.TargetClassName}.{association.SourcePropertyTypeName}");
                log.Debug("\n   " + JsonConvert.SerializeObject(association));
                result.Add(association);
            }

            return(result);
        }
예제 #17
0
        internal override void Configure(
            AssociationType associationType,
            AssociationEndMember dependentEnd,
            EntityTypeConfiguration entityTypeConfiguration)
        {
            // ISSUE: object of a compiler-generated type is created
            // ISSUE: variable of a compiler-generated type
            ForeignKeyConstraintConfiguration.\u003C\u003Ec__DisplayClasse cDisplayClasse1 = new ForeignKeyConstraintConfiguration.\u003C\u003Ec__DisplayClasse();
            // ISSUE: reference to a compiler-generated field
            cDisplayClasse1.entityTypeConfiguration = entityTypeConfiguration;
            if (!this._dependentProperties.Any <PropertyInfo>())
            {
                return;
            }
            IEnumerable <PropertyInfo> propertyInfos = this._dependentProperties.AsEnumerable <PropertyInfo>();

            if (!this.IsFullySpecified)
            {
                // ISSUE: reference to a compiler-generated field
                if (EntityTypeExtensions.GetClrType(dependentEnd.GetEntityType()) != cDisplayClasse1.entityTypeConfiguration.ClrType)
                {
                    return;
                }
                // ISSUE: reference to a compiler-generated method
                IEnumerable <\u003C\u003Ef__AnonymousType41 <PropertyInfo, int?> > source = this._dependentProperties.Select(new Func <PropertyInfo, \u003C\u003Ef__AnonymousType41 <PropertyInfo, int?> >(cDisplayClasse1.\u003CConfigure\u003Eb__0));
                if (this._dependentProperties.Count > 1 && source.Any(p => !p.ColumnOrder.HasValue))
                {
                    ReadOnlyMetadataCollection <EdmProperty> dependentKeys = dependentEnd.GetEntityType().KeyProperties;
                    if (dependentKeys.Count != this._dependentProperties.Count || !source.All(fk =>
                    {
                        // ISSUE: variable of a compiler-generated type
                        ForeignKeyConstraintConfiguration.\u003C\u003Ec__DisplayClasse cDisplayClasse = cDisplayClasse1;
                        var fk1 = fk;
                        return(dependentKeys.Any <EdmProperty>((Func <EdmProperty, bool>)(p => p.GetClrPropertyInfo().IsSameAs(fk1.PropertyInfo))));
                    }))
                    {
                        // ISSUE: reference to a compiler-generated field
                        throw Error.ForeignKeyAttributeConvention_OrderRequired((object)cDisplayClasse1.entityTypeConfiguration.ClrType);
                    }
                    propertyInfos = dependentKeys.Select <EdmProperty, PropertyInfo>((Func <EdmProperty, PropertyInfo>)(p => p.GetClrPropertyInfo()));
                }
                else
                {
                    propertyInfos = source.OrderBy(p => p.ColumnOrder).Select(p => p.PropertyInfo);
                }
            }
            List <EdmProperty> edmPropertyList = new List <EdmProperty>();

            foreach (PropertyInfo propertyInfo in propertyInfos)
            {
                EdmProperty primitiveProperty = dependentEnd.GetEntityType().GetDeclaredPrimitiveProperty(propertyInfo);
                if (primitiveProperty == null)
                {
                    throw Error.ForeignKeyPropertyNotFound((object)propertyInfo.Name, (object)dependentEnd.GetEntityType().Name);
                }
                edmPropertyList.Add(primitiveProperty);
            }
            AssociationEndMember  otherEnd = associationType.GetOtherEnd(dependentEnd);
            ReferentialConstraint referentialConstraint = new ReferentialConstraint((RelationshipEndMember)otherEnd, (RelationshipEndMember)dependentEnd, (IEnumerable <EdmProperty>)otherEnd.GetEntityType().KeyProperties, (IEnumerable <EdmProperty>)edmPropertyList);

            if (otherEnd.IsRequired())
            {
                referentialConstraint.ToProperties.Each <EdmProperty, bool>((Func <EdmProperty, bool>)(p => p.Nullable = false));
            }
            associationType.Constraint = referentialConstraint;
        }
예제 #18
0
        private static void GenerateForeignKeyAssociationType(
            AssociationType associationType,
            DbDatabaseMapping databaseMapping)
        {
            AssociationEndMember dependentEnd               = associationType.Constraint.DependentEnd;
            AssociationEndMember otherEnd                   = associationType.GetOtherEnd(dependentEnd);
            EntityTypeMapping    mappingInHierarchy         = StructuralTypeMappingGenerator.GetEntityTypeMappingInHierarchy(databaseMapping, otherEnd.GetEntityType());
            EntityTypeMapping    dependentEntityTypeMapping = StructuralTypeMappingGenerator.GetEntityTypeMappingInHierarchy(databaseMapping, dependentEnd.GetEntityType());
            ForeignKeyBuilder    foreignKeyBuilder          = new ForeignKeyBuilder(databaseMapping.Database, associationType.Name)
            {
                PrincipalTable = mappingInHierarchy.MappingFragments.Single <MappingFragment>().Table,
                DeleteAction   = otherEnd.DeleteBehavior != OperationAction.None ? otherEnd.DeleteBehavior : OperationAction.None
            };

            dependentEntityTypeMapping.MappingFragments.Single <MappingFragment>().Table.AddForeignKey(foreignKeyBuilder);
            foreignKeyBuilder.DependentColumns = associationType.Constraint.ToProperties.Select <EdmProperty, EdmProperty>((Func <EdmProperty, EdmProperty>)(dependentProperty => dependentEntityTypeMapping.GetPropertyMapping(dependentProperty).ColumnProperty));
            foreignKeyBuilder.SetAssociationType(associationType);
        }