src/Misc/EFTools/EntityDesignModel/Integrity/CreateForeignKeyProperties.cs
/// <summary>
///     This method will first determine the principal and dependent ends of the passed in Association.
///     It will create a property on the dependent end for each principal key property.
/// </summary>
This method will first determine the principal and dependent ends of the passed in Association.
It will create a property on the dependent end for each principal key property.
This method will first determine the principal and dependent ends of the passed in Association . It will create a property on the dependent end for each principal key property .
[SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
        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, "Creating foreign key properties 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 create foreign key properties");
            Debug.Assert(
                _association.AssociationSet != null,
                "The association being processed does not have a valid AssociationSet while trying to create foreign key properties");
            if (_association.ReferentialConstraint != null)
            {
                DeleteEFElementCommand.DeleteInTransaction(_context, _association.ReferentialConstraint);
            }
            AssociationEnd principal = null;
            AssociationEnd dependent = null;
            ModelHelper.DeterminePrincipalDependentAssociationEnds(
                _association, out principal, out dependent,
                ModelHelper.DeterminePrincipalDependentAssociationEndsScenario.CreateForeignKeyProperties);
            if (principal != null
                && principal.Type.Target != null
                && dependent != null
                && dependent.Type.Target != null)
            {
                if (principal.Multiplicity.Value == ModelConstants.Multiplicity_Many
                    && dependent.Multiplicity.Value == ModelConstants.Multiplicity_Many)
                {
                    return;
                }
                var principalPropertyRefs = new HashSet<Property>();
                var dependentPropertyRefs = new HashSet<Property>();
                IEnumerable<Property> pkeys;
                var cet = principal.Type.Target as ConceptualEntityType;
                if (cet != null)
                {
                    pkeys = cet.ResolvableTopMostBaseType.ResolvableKeys;
                }
                else
                {
                    pkeys = principal.Type.Target.ResolvableKeys;
                }
                foreach (var pkey in pkeys)
                {
                     get a unique name for this new property
                    var fkeyName = string.Format(
                        CultureInfo.CurrentCulture, "{0}{1}{2}",
                        principal.Type.Target.LocalName.Value,
                        (char.IsUpper(pkey.LocalName.Value, 0) ? "" : "_"),
                        pkey.LocalName.Value);
                    fkeyName = ModelHelper.GetUniqueName(typeof(Property), dependent.Type.Target, fkeyName);
                     tweak the properties; we are using the copy/paste process since we have to 
                     copy all facets of the pk and that code does this already
                    var pcf = new PropertyClipboardFormat(pkey);
                    pcf.PropertyName = fkeyName;
                    pcf.IsKeyProperty = false;
                    pcf.IsNullable = (principal.Multiplicity.Value == ModelConstants.Multiplicity_ZeroOrOne ? true : false);
                    pcf.StoreGeneratedPattern = string.Empty;
                    pcf.GetterAccessModifier = string.Empty;
                    pcf.SetterAccessModifier = string.Empty;
                     create the new property
                    var cmd = new CopyPropertyCommand(pcf, dependent.Type.Target);
                    CommandProcessor.InvokeSingleCommand(_context, cmd);
                    var fkey = cmd.Property;
                     build up our list of keys
                    Debug.Assert(fkey != null, "CreateForeignKeyProperties was not able to create a foreign key");
                    if (fkey != null)
                    {
                        principalPropertyRefs.Add(pkey);
                        dependentPropertyRefs.Add(fkey);
                    }
                }
                 create the new RC
                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 ( " " , " " ) ] 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 , " " ) ; if ( _association . ReferentialConstraint != null ) { DeleteEFElementCommand . DeleteInTransaction ( _context , _association . ReferentialConstraint ) ; } AssociationEnd principal = null ; AssociationEnd dependent = null ; ModelHelper . DeterminePrincipalDependentAssociationEnds ( _association , out principal , out dependent , ModelHelper . DeterminePrincipalDependentAssociationEndsScenario . CreateForeignKeyProperties ) ; if ( principal != null && principal . Type . Target != null && dependent != null && dependent . Type . Target != null ) { if ( principal . Multiplicity . Value == ModelConstants . Multiplicity_Many && dependent . Multiplicity . Value == ModelConstants . Multiplicity_Many ) { return ; } var principalPropertyRefs = new HashSet < Property > ( ) ; var dependentPropertyRefs = new HashSet < Property > ( ) ; IEnumerable < Property > pkeys ; var cet = principal . Type . Target as ConceptualEntityType ; if ( cet != null ) { pkeys = cet . ResolvableTopMostBaseType . ResolvableKeys ; } else { pkeys = principal . Type . Target . ResolvableKeys ; } foreach ( var pkey in pkeys ) { var fkeyName = string . Format ( CultureInfo . CurrentCulture , " " , principal . Type . Target . LocalName . Value , ( char . IsUpper ( pkey . LocalName . Value , 0 ) ? " " : " " ) , pkey . LocalName . Value ) ; fkeyName = ModelHelper . GetUniqueName ( typeof ( Property ) , dependent . Type . Target , fkeyName ) ; var pcf = new PropertyClipboardFormat ( pkey ) ; pcf . PropertyName = fkeyName ; pcf . IsKeyProperty = false ; pcf . IsNullable = ( principal . Multiplicity . Value == ModelConstants . Multiplicity_ZeroOrOne ? true : false ) ; pcf . StoreGeneratedPattern = string . Empty ; pcf . GetterAccessModifier = string . Empty ; pcf . SetterAccessModifier = string . Empty ; var cmd = new CopyPropertyCommand ( pcf , dependent . Type . Target ) ; CommandProcessor . InvokeSingleCommand ( _context , cmd ) ; var fkey = cmd . Property ; Debug . Assert ( fkey != null , " " ) ; if ( fkey != null ) { principalPropertyRefs . Add ( pkey ) ; dependentPropertyRefs . Add ( fkey ) ; } } 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 the principal and dependent ends of the passed in Association.
This method will first determine the principal and dependent ends of 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 aren't supported in this EF version, then we skip all processing here.  // remove any existing RC // figure out the principal and dependent ends // many-to-many associations don't need foreign key properties // add properties to the dependent side // the principal is a c-side entity // the principal is an s-side entity // build up the foreign key name, add an '_' if the resulting name wouldn't be camel-case // e.g.  //  Order and Id become "OrderId" //  order and id become "order_id" // // get a unique name for this new property // tweak the properties; we are using the copy/paste process since we have to  // copy all facets of the pk and that code does this already // create the new property // build up our list of keys // create the new RC