Exemplo n.º 1
0
        internal static IEnumerable <Command> LaunchReferentialConstraintDialog(Association association)
        {
            var commands = new List <Command>();

            if (association != null)
            {
                if (association.ReferentialConstraint == null
                    ||
                    (association.ReferentialConstraint != null &&
                     association.ReferentialConstraint.Principal != null &&
                     association.ReferentialConstraint.Principal.Role.Target != null &&
                     association.ReferentialConstraint.Principal.Role.Target.Type.Target != null &&
                     association.ReferentialConstraint.Dependent != null &&
                     association.ReferentialConstraint.Dependent.Role.Target != null &&
                     association.ReferentialConstraint.Dependent.Role.Target.Type.Target != null
                    )
                    )
                {
                    using (var dlg = new ReferentialConstraintDialog(association))
                    {
                        var result = dlg.ShowDialog();
                        if (result != DialogResult.Cancel &&
                            dlg.Principal != null &&
                            dlg.Dependent != null)
                        {
                            if (association.ReferentialConstraint != null)
                            {
                                // first, enqueue the delete command (always)
                                commands.Add(association.ReferentialConstraint.GetDeleteCommand());
                            }

                            if (dlg.ShouldDeleteOnly == false)
                            {
                                var principalProps = new List <Property>();
                                var dependentProps = new List <Property>();

                                var keys = GetKeysForType(dlg.Principal.Type.Target);

                                foreach (var mli in dlg.MappingList)
                                {
                                    if (mli.IsValidPrincipalKey)
                                    {
                                        // try to resolve the symbol into a property
                                        Property p = null;
                                        Property d = null;
                                        if (mli.PrincipalKey != null)
                                        {
                                            p = GetKeyForType(mli.PrincipalKey, dlg.Principal.Type.Target, keys);
                                        }

                                        if (mli.DependentProperty != null)
                                        {
                                            d = dlg.Dependent.Artifact.ArtifactSet.LookupSymbol(mli.DependentProperty) as Property;
                                        }

                                        if (p != null &&
                                            d != null)
                                        {
                                            principalProps.Add(p);
                                            dependentProps.Add(d);
                                        }
                                    }
                                }

                                // now enqueue the command to create a new one if the user didn't click Delete
                                Debug.Assert(
                                    principalProps.Count == dependentProps.Count,
                                    "principal (" + principalProps.Count + ") & dependent (" + dependentProps.Count
                                    + ") property counts must match!");
                                if (principalProps.Count > 0)
                                {
                                    Command cmd = new CreateReferentialConstraintCommand(
                                        dlg.Principal,
                                        dlg.Dependent,
                                        principalProps,
                                        dependentProps);
                                    commands.Add(cmd);
                                }
                            }
                        }
                    }
                }
                else
                {
                    VsUtils.ShowMessageBox(
                        PackageManager.Package,
                        Resources.Error_CannotEditRefConstraint,
                        OLEMSGBUTTON.OLEMSGBUTTON_OK,
                        OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST,
                        OLEMSGICON.OLEMSGICON_WARNING);
                }
            }
            return(commands);
        }
Exemplo n.º 2
0
        public void Invoke()
        {
            Debug.Assert(_association != null, "The Association reference is null");

            // if the association was deleted in this transaction, just return since we won't need to process it
            if (_association == null ||
                _association.XObject == null)
            {
                return;
            }

            // if foreign keys aren't supported in this EF version, then we skip all processing here.
            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");

            // remove any existing RC
            if (_association.ReferentialConstraint != null)
            {
                DeleteEFElementCommand.DeleteInTransaction(_context, _association.ReferentialConstraint);
            }

            // figure out the principal and dependent ends
            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)
            {
                // many-to-many associations don't need foreign key properties
                if (principal.Multiplicity.Value == ModelConstants.Multiplicity_Many &&
                    dependent.Multiplicity.Value == ModelConstants.Multiplicity_Many)
                {
                    return;
                }

                var principalPropertyRefs = new HashSet <Property>();
                var dependentPropertyRefs = new HashSet <Property>();

                // add properties to the dependent side

                IEnumerable <Property> pkeys;
                var cet = principal.Type.Target as ConceptualEntityType;
                if (cet != null)
                {
                    // the principal is a c-side entity
                    pkeys = cet.ResolvableTopMostBaseType.ResolvableKeys;
                }
                else
                {
                    // the principal is an s-side entity
                    pkeys = principal.Type.Target.ResolvableKeys;
                }

                foreach (var pkey in pkeys)
                {
                    // 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
                    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);
                }
            }
        }
Exemplo n.º 3
0
        public void Invoke()
        {
            Debug.Assert(_association != null, "The Association reference is null");

            // if the association was deleted in this transaction, just return since we won't need to process it
            if (_association == null ||
                _association.XObject == null)
            {
                return;
            }

            // if foreign keys are supported in this EF version, then we skip all processing here.
            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");

            // some local aliases for readability
            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;
            }

            // regardless, we will remove the constraint
            if (_association.ReferentialConstraint != null)
            {
                DeleteEFElementCommand.DeleteInTransaction(_context, _association.ReferentialConstraint);
            }

            // we will never create a constraint against a self-association
            if (end1.Type.Target == end2.Type.Target)
            {
                return;
            }

            AssociationEnd principal = null;
            AssociationEnd dependent = null;

            ModelHelper.DeterminePrincipalDependentAssociationEnds(
                _association, out principal, out dependent,
                ModelHelper.DeterminePrincipalDependentAssociationEndsScenario.InferReferentialConstraint);

            // 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
            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)
                    {
                        // any commonly mapped properties will be loaded into these HashSets
                        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)
                        {
                            // 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
                            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)
                            {
                                // if the propertyRefs sets have any data in them, add the constraint
                                var cmd = new CreateReferentialConstraintCommand(
                                    principal, dependent, principalPropertyRefs, dependentPropertyRefs);
                                CommandProcessor.InvokeSingleCommand(_context, cmd);
                            }
                        }
                    }
                }
            }
        }