internal override void Configure(
     EdmAssociationType associationType, EdmAssociationEnd dependentEnd,
     EntityTypeConfiguration entityTypeConfiguration)
 {
     //Contract.Requires(associationType != null);
     //Contract.Requires(dependentEnd != null);
     //Contract.Requires(entityTypeConfiguration != null);
 }
        public static EdmAssociationEnd GetOtherEnd(
            this EdmAssociationType associationType, EdmAssociationEnd associationEnd)
        {
            Contract.Requires(associationType != null);
            Contract.Requires(associationEnd != null);

            return associationEnd == associationType.SourceEnd
                       ? associationType.TargetEnd
                       : associationType.SourceEnd;
        }
        private void ConfigureDeleteAction(EdmAssociationEnd principalEnd)
        {
            //Contract.Requires(principalEnd != null);

            if (DeleteAction != null)
            {
                principalEnd.DeleteAction = DeleteAction.Value;
            }
        }
        private void ConfigureConstraint(
            EdmAssociationType associationType,
            EdmAssociationEnd dependentEnd,
            EntityTypeConfiguration entityTypeConfiguration)
        {
            //Contract.Requires(associationType != null);
            //Contract.Requires(dependentEnd != null);
            //Contract.Requires(entityTypeConfiguration != null);

            if (_constraint != null)
            {
                _constraint.Configure(associationType, dependentEnd, entityTypeConfiguration);

                var associationConstraint = associationType.Constraint;

                if ((associationConstraint != null)
                    && associationConstraint.DependentProperties
                           .SequenceEqual(associationConstraint.DependentEnd.EntityType.DeclaredKeyProperties))
                {
                    // The dependent FK is also the PK. We need to adjust the multiplicity
                    // when it has not been explicity configured because the default is *:0..1

                    if ((_inverseEndKind == null)
                        && associationType.SourceEnd.IsMany())
                    {
                        associationType.SourceEnd.EndKind = EdmAssociationEndKind.Optional;
                        associationType.TargetEnd.EndKind = EdmAssociationEndKind.Required;
                    }
                }
            }
        }
        public void IsMany_should_return_true_when_end_kind_is_many()
        {
            var associationEnd = new EdmAssociationEnd { EndKind = EdmAssociationEndKind.Many };

            Assert.True(associationEnd.IsMany());
        }
        public void IsRequired_should_return_true_when_end_kind_is_required()
        {
            var associationEnd = new EdmAssociationEnd { EndKind = EdmAssociationEndKind.Required };

            Assert.True(associationEnd.IsRequired());
        }
        public void IsOptional_should_return_true_when_end_kind_is_optional()
        {
            var associationEnd = new EdmAssociationEnd { EndKind = EdmAssociationEndKind.Optional };

            Assert.True(associationEnd.IsOptional());
        }
 internal override void Configure(
     EdmAssociationType associationType, EdmAssociationEnd dependentEnd,
     EntityTypeConfiguration entityTypeConfiguration)
 {
     associationType.MarkIndependent();
 }
        internal override void Configure(
            EdmAssociationType associationType, EdmAssociationEnd dependentEnd,
            EntityTypeConfiguration entityTypeConfiguration)
        {
            if (!_dependentProperties.Any())
            {
                return;
            }

            var associationConstraint
                = new EdmAssociationConstraint
                    {
                        DependentEnd = dependentEnd
                    };

            var dependentProperties = _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.EntityType.DeclaredKeyProperties;

                    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
                        dependentProperties = dependentKeys.Select(p => p.GetClrPropertyInfo());
                    }
                    else
                    {
                        throw Error.ForeignKeyAttributeConvention_OrderRequired(entityTypeConfiguration.ClrType);
                    }
                }
                else
                {
                    dependentProperties = foreignKeys.OrderBy(p => p.ColumnOrder).Select(p => p.PropertyInfo);
                }
            }

            foreach (var dependentProperty in dependentProperties)
            {
                var property
                    = associationConstraint
                        .DependentEnd
                        .EntityType
                        .GetDeclaredPrimitiveProperty(dependentProperty);

                if (property == null)
                {
                    throw Error.ForeignKeyPropertyNotFound(
                        dependentProperty.Name, associationConstraint.DependentEnd.EntityType.Name);
                }

                associationConstraint.DependentProperties.Add(property);
            }

            associationType.Constraint = associationConstraint;

            var principalEnd = associationType.GetOtherEnd(dependentEnd);

            if (principalEnd.IsRequired())
            {
                associationType.Constraint.DependentProperties.Each(p => p.PropertyType.IsNullable = false);
            }
        }
        /// <summary>
        ///     Attempt to determine the principal and dependent ends of this association.
        /// 
        ///     The following table illustrates the solution space.
        ///  
        ///     Source | Target || Prin  | Dep   |
        ///     -------|--------||-------|-------|
        ///     1      | 1      || -     | -     | 
        ///     1      | 0..1   || Sr    | Ta    |
        ///     1      | *      || Sr    | Ta    |
        ///     0..1   | 1      || Ta    | Sr    |
        ///     0..1   | 0..1   || -     | -     |
        ///     0..1   | *      || Sr    | Ta    |
        ///     *      | 1      || Ta    | Sr    |
        ///     *      | 0..1   || Ta    | Sr    |
        ///     *      | *      || -     | -     |
        /// </summary>
        public static bool TryGuessPrincipalAndDependentEnds(
            this EdmAssociationType associationType,
            out EdmAssociationEnd principalEnd,
            out EdmAssociationEnd dependentEnd)
        {
            Contract.Requires(associationType != null);
            Contract.Assert(associationType.SourceEnd != null);
            Contract.Assert(associationType.TargetEnd != null);

            principalEnd = dependentEnd = null;

            var sourceEnd = associationType.SourceEnd;
            var targetEnd = associationType.TargetEnd;

            if (sourceEnd.EndKind
                != targetEnd.EndKind)
            {
                principalEnd
                    = (sourceEnd.IsRequired()
                       || (sourceEnd.IsOptional() && targetEnd.IsMany()))
                          ? sourceEnd
                          : targetEnd;

                dependentEnd
                    = (principalEnd == sourceEnd)
                          ? targetEnd
                          : sourceEnd;
            }

            return (principalEnd != null);
        }
 internal abstract void Configure(
     EdmAssociationType associationType, EdmAssociationEnd dependentEnd,
     EntityTypeConfiguration entityTypeConfiguration);
        private void GenerateIndependentForeignKeyConstraint(
            DbDatabaseMapping databaseMapping,
            EdmEntityType principalEntityType,
            EdmEntityType dependentEntityType,
            DbTableMetadata dependentTable,
            DbAssociationSetMapping associationSetMapping,
            DbAssociationEndMapping associationEndMapping,
            string name,
            EdmAssociationEnd principalEnd,
            bool isPrimaryKeyColumn = false)
        {
            //Contract.Requires(databaseMapping != null);
            //Contract.Requires(principalEntityType != null);
            //Contract.Requires(dependentTable != null);
            //Contract.Requires(associationEndMapping != null);
            //Contract.Requires(!string.IsNullOrWhiteSpace(name));

            var principalTable
                = GetEntityTypeMappingInHierarchy(databaseMapping, principalEntityType)
                    .TypeMappingFragments
                    .Single()
                    .Table;

            var foreignKeyConstraint = new DbForeignKeyConstraintMetadata
                {
                    Name = name,
                    PrincipalTable = principalTable,
                    DeleteAction = associationEndMapping.AssociationEnd.DeleteAction.HasValue
                                       ? (DbOperationAction)
                                         associationEndMapping.AssociationEnd.DeleteAction.
                                             Value
                                       : DbOperationAction.None
                };

            var principalNavigationProperty
                = databaseMapping.Model.GetEntityTypes()
                    .SelectMany(e => e.DeclaredNavigationProperties)
                    .SingleOrDefault(n => n.ResultEnd == principalEnd);

            GenerateIndependentForeignKeyColumns(
                principalEntityType,
                dependentEntityType,
                associationSetMapping,
                associationEndMapping,
                dependentTable,
                foreignKeyConstraint,
                isPrimaryKeyColumn,
                principalNavigationProperty);

            dependentTable.ForeignKeyConstraints.Add(foreignKeyConstraint);
        }
        private static DbAssociationSetMapping GenerateAssociationSetMapping(
            EdmAssociationType associationType,
            DbDatabaseMapping databaseMapping,
            EdmAssociationEnd principalEnd,
            EdmAssociationEnd dependentEnd,
            DbTableMetadata dependentTable)
        {
            //Contract.Requires(associationType != null);
            //Contract.Requires(databaseMapping != null);
            //Contract.Requires(principalEnd != null);
            //Contract.Requires(dependentEnd != null);
            //Contract.Requires(dependentTable != null);

            var associationSetMapping
                = databaseMapping.AddAssociationSetMapping(
                    databaseMapping.Model.GetAssociationSet(associationType));

            associationSetMapping.Table = dependentTable;
            associationSetMapping.SourceEndMapping.AssociationEnd = principalEnd;
            associationSetMapping.TargetEndMapping.AssociationEnd = dependentEnd;

            return associationSetMapping;
        }