src/Misc/EFTools/EntityDesignModel/Integrity/InferReferentialContraints.cs
/// <summary>
///     This method will first determine whether a referential constraint is needed for the
///     passed in Association.  If yes, it will create one (or recreate as needed).  If no, it
///     will delete one if it exists.
/// </summary>
/// <param name="cpc"></param>
/// <param name="association">This is only valid for C-Side associations.</param>
This method will first determine whether a referential constraint is needed for the
passed in Association.  If yes, it will create one (or recreate as needed).  If no, it
will delete one if it exists.
This method will first determine whether a referential constraint is needed for the passed in Association . If yes it will create one ( or recreate as needed ) . If no it will delete one if it exists .
[SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
        [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
        public void Invoke()
        {
            Debug.Assert(_association != null, "The Association reference is null");
            if (_association == null
                || _association.XObject == null)
            {
                return;
            }
            if (EdmFeatureManager.GetForeignKeysInModelFeatureState(_association.Artifact.SchemaVersion).IsEnabled())
            {
                return;
            }
            Debug.Assert(_association.EntityModel.IsCSDL, "Inferring ref constraints isn't valid for SSDL associations");
            Debug.Assert(
                _association.AssociationEnds().Count == 2,
                "The association to be processed does not have 2 ends while trying to infer ref constraints");
            Debug.Assert(
                _association.AssociationSet != null,
                "The association being processed does not have a valid AssociationSet while trying to infer ref constraints");
            var end1 = _association.AssociationEnds()[0];
            var end2 = _association.AssociationEnds()[1];
            Debug.Assert(end1 != null && end2 != null, "Null end found while trying to infer ref constraints");
            if (end1 == null
                || end2 == null)
            {
                return;
            }
            if (_association.ReferentialConstraint != null)
            {
                DeleteEFElementCommand.DeleteInTransaction(_context, _association.ReferentialConstraint);
            }
            if (end1.Type.Target == end2.Type.Target)
            {
                return;
            }
            AssociationEnd principal = null;
            AssociationEnd dependent = null;
            ModelHelper.DeterminePrincipalDependentAssociationEnds(
                _association, out principal, out dependent,
                ModelHelper.DeterminePrincipalDependentAssociationEndsScenario.InferReferentialConstraint);
            if (principal != null
                && principal.Type.Target != null
                && dependent != null
                && dependent.Type.Target != null)
            {
                var associationSet = _association.AssociationSet;
                if (associationSet != null)
                {
                    var asm = associationSet.AssociationSetMapping;
                    if (asm != null
                        && asm.EndProperties().Count == 2)
                    {
                        var principalPropertyRefs = new HashSet<Property>();
                        var dependentPropertyRefs = new HashSet<Property>();
                        EndProperty dependentEndProperty = null;
                        EndProperty principalEndProperty = null;
                        var endProp1 = asm.EndProperties()[0];
                        var endProp2 = asm.EndProperties()[1];
                        if (endProp1.Name.Target != null)
                        {
                            if (endProp1.Name.Target.Role.Target == dependent)
                            {
                                dependentEndProperty = endProp1;
                                principalEndProperty = endProp2;
                            }
                            else
                            {
                                dependentEndProperty = endProp2;
                                principalEndProperty = endProp1;
                            }
                        }
                        Debug.Assert(
                            dependentEndProperty != null && principalEndProperty != null,
                            "Either dependent or principal EndProperty is null");
                        if (dependentEndProperty != null
                            && principalEndProperty != null)
                        {
                            foreach (var dependentScalarProp in dependentEndProperty.ScalarProperties())
                            {
                                var principalScalarProp =
                                    principalEndProperty.ScalarProperties()
                                    .FirstOrDefault(psp => psp.ColumnName.Target == dependentScalarProp.ColumnName.Target);
                                if (principalScalarProp != null)
                                {
                                    principalPropertyRefs.Add(principalScalarProp.Name.Target);
                                    dependentPropertyRefs.Add(dependentScalarProp.Name.Target);
                                }
                            }
                            Debug.Assert(
                                principalPropertyRefs.Count == dependentPropertyRefs.Count,
                                "List of keys are mismatched while trying to create a Ref Constraint");
                            if (principalPropertyRefs.Count > 0
                                && dependentPropertyRefs.Count > 0
                                && principalPropertyRefs.Count == dependentPropertyRefs.Count)
                            {
                                var cmd = new CreateReferentialConstraintCommand(
                                    principal, dependent, principalPropertyRefs, dependentPropertyRefs);
                                CommandProcessor.InvokeSingleCommand(_context, cmd);
                            }
                        }
                    }
                }
            }
        }
[ SuppressMessage ( " " , " " ) ] [ SuppressMessage ( " " , " " ) ] public void Invoke ( ) { Debug . Assert ( _association != null , " " ) ; if ( _association == null || _association . XObject == null ) { return ; } if ( EdmFeatureManager . GetForeignKeysInModelFeatureState ( _association . Artifact . SchemaVersion ) . IsEnabled ( ) ) { return ; } Debug . Assert ( _association . EntityModel . IsCSDL , " " ) ; Debug . Assert ( _association . AssociationEnds ( ) . Count == 2 , " " ) ; Debug . Assert ( _association . AssociationSet != null , " " ) ; var end1 = _association . AssociationEnds ( ) [ 0 ] ; var end2 = _association . AssociationEnds ( ) [ 1 ] ; Debug . Assert ( end1 != null && end2 != null , " " ) ; if ( end1 == null || end2 == null ) { return ; } if ( _association . ReferentialConstraint != null ) { DeleteEFElementCommand . DeleteInTransaction ( _context , _association . ReferentialConstraint ) ; } if ( end1 . Type . Target == end2 . Type . Target ) { return ; } AssociationEnd principal = null ; AssociationEnd dependent = null ; ModelHelper . DeterminePrincipalDependentAssociationEnds ( _association , out principal , out dependent , ModelHelper . DeterminePrincipalDependentAssociationEndsScenario . InferReferentialConstraint ) ; if ( principal != null && principal . Type . Target != null && dependent != null && dependent . Type . Target != null ) { var associationSet = _association . AssociationSet ; if ( associationSet != null ) { var asm = associationSet . AssociationSetMapping ; if ( asm != null && asm . EndProperties ( ) . Count == 2 ) { var principalPropertyRefs = new HashSet < Property > ( ) ; var dependentPropertyRefs = new HashSet < Property > ( ) ; EndProperty dependentEndProperty = null ; EndProperty principalEndProperty = null ; var endProp1 = asm . EndProperties ( ) [ 0 ] ; var endProp2 = asm . EndProperties ( ) [ 1 ] ; if ( endProp1 . Name . Target != null ) { if ( endProp1 . Name . Target . Role . Target == dependent ) { dependentEndProperty = endProp1 ; principalEndProperty = endProp2 ; } else { dependentEndProperty = endProp2 ; principalEndProperty = endProp1 ; } } Debug . Assert ( dependentEndProperty != null && principalEndProperty != null , " " ) ; if ( dependentEndProperty != null && principalEndProperty != null ) { foreach ( var dependentScalarProp in dependentEndProperty . ScalarProperties ( ) ) { var principalScalarProp = principalEndProperty . ScalarProperties ( ) . FirstOrDefault ( psp => psp . ColumnName . Target == dependentScalarProp . ColumnName . Target ) ; if ( principalScalarProp != null ) { principalPropertyRefs . Add ( principalScalarProp . Name . Target ) ; dependentPropertyRefs . Add ( dependentScalarProp . Name . Target ) ; } } Debug . Assert ( principalPropertyRefs . Count == dependentPropertyRefs . Count , " " ) ; if ( principalPropertyRefs . Count > 0 && dependentPropertyRefs . Count > 0 && principalPropertyRefs . Count == dependentPropertyRefs . Count ) { var cmd = new CreateReferentialConstraintCommand ( principal , dependent , principalPropertyRefs , dependentPropertyRefs ) ; CommandProcessor . InvokeSingleCommand ( _context , cmd ) ; } } } } } }
This method will first determine whether a referential constraint is needed for the
passed in Association.
This method will first determine whether a referential constraint is needed for the passed in Association .
// if the association was deleted in this transaction, just return since we won't need to process it // if foreign keys are supported in this EF version, then we skip all processing here.  // some local aliases for readability // regardless, we will remove the constraint // we will never create a constraint against a self-association // We found our principal and dependent ends but we still need to confirm that // the AssociationSetMapping contains key properties that are mapped to the same column // any commonly mapped properties will be loaded into these HashSets // for each column that is mapped to a key property on the dependent end, determine if there is a  // key property on the principal end that it is also mapped to. If there is, then we need a // ReferentialConstraint // if the propertyRefs sets have any data in them, add the constraint
cpc
None
association
This is only valid for C-Side associations.
This is only valid for C - Side associations .