private CreateEndScalarPropertyCommand(
     AssociationSetMapping associationSetMapping, AssociationSetEnd associationSetEnd, Property entityProperty, Property tableColumn,
     bool enforceConstraints)
 {
     Initialize(entityProperty, tableColumn, enforceConstraints);
     CommandValidation.ValidateAssociationSetMapping(associationSetMapping);
     CommandValidation.ValidateAssociationSetEnd(associationSetEnd);
     _associationSetMapping = associationSetMapping;
     _associationSetEnd = associationSetEnd;
 }
        /// <summary>
        ///     Creates a Condition in the given AssociationSetMapping.
        ///     Valid combinations are:
        ///     1. Send true or false for isNull, and null for conditionValue
        ///     2. Send null for isNull, and a non-empty string for conditionValue
        ///     3. Send null for isNull, and null for conditionValue
        ///     You cannot send non-null values to both arguments.
        /// </summary>
        /// <param name="mappingFragment">The AssociationSetMapping to place this Condition; cannot be null.</param>
        /// <param name="tableColumn">This must be a valid Property from the S-Model.</param>
        internal CreateEndConditionCommand(
            AssociationSetMapping associationSetMapping, Property tableColumn, bool? isNull, string conditionValue)
        {
            CommandValidation.ValidateAssociationSetMapping(associationSetMapping);
            CommandValidation.ValidateTableColumn(tableColumn);

            _associationSetMapping = associationSetMapping;
            _tableColumn = tableColumn;
            _isNull = isNull;
            _conditionValue = conditionValue;
        }
        internal static AssociationIdentity CreateAssociationIdentity(AssociationSetMapping asm)
        {
            var sSideEntitySet = asm.StoreEntitySet.Target as StorageEntitySet;
            if (null == sSideEntitySet)
            {
                // a null sSideEntitySet indicates an unresolved AssociationSetMapping
                // we treat this as equivalent to the AssociationSet being unmapped
                return null;
            }

            var assocId = new AssociationIdentityForAssociationSetMapping();
            assocId._assocTable = DatabaseObject.CreateFromEntitySet(sSideEntitySet);
            foreach (var endProp in asm.EndProperties())
            {
                var assocEndId = new AssociationEndIdentity(endProp);
                assocId.AddAssociationEndIdentity(assocEndId);
            }

            return assocId;
        }
        protected override void InvokeInternal(CommandProcessorContext cpc)
        {
            // if we don't have an ECM yet, go create one
            if (EntityContainerMapping == null)
            {
                var createECM = new CreateEntityContainerMappingCommand(AssociationSet.Artifact);
                CommandProcessor.InvokeSingleCommand(cpc, createECM);
                EntityContainerMapping = createECM.EntityContainerMapping;
            }

            Debug.Assert(EntityContainerMapping != null, "EntityContainerMapping should not be null");
            if (EntityContainerMapping == null)
            {
                throw new CannotLocateParentItemException();
            }

            // create the ETM
            var asm = new AssociationSetMapping(EntityContainerMapping, null);
            asm.Name.SetRefName(AssociationSet);
            asm.TypeName.SetRefName(Association);
            asm.StoreEntitySet.SetRefName(StorageEntitySet);
            EntityContainerMapping.AddAssociationSetMapping(asm);

            XmlModelHelper.NormalizeAndResolve(asm);

            Debug.Assert(asm.Name.Target != null, "Could not resolve association set reference");
            Debug.Assert(asm.TypeName.Target != null, "Could not resolve association type reference");
            Debug.Assert(asm.StoreEntitySet.Target != null, "Could not resolve table reference");

            var assoc = asm.TypeName.Target;
            Debug.Assert(assoc != null, "Could not resolve association reference");
            if (assoc != null)
            {
                InferReferentialConstraints.AddRule(cpc, assoc);
            }

            _created = asm;
        }
 /// <summary>
 ///     Creates an EndProperty and then creates the ScalarProperty in that End.
 /// </summary>
 /// <param name="associationSetMapping"></param>
 /// <param name="associationSetEnd"></param>
 /// <param name="entityProperty">This must be a valid Property from the C-Model.</param>
 /// <param name="tableColumn">This must be a valid Property from the S-Model.</param>
 internal CreateEndScalarPropertyCommand(
     AssociationSetMapping associationSetMapping, AssociationSetEnd associationSetEnd, Property entityProperty, Property tableColumn)
     : this(associationSetMapping, associationSetEnd, entityProperty, tableColumn, true)
 {
 }
 internal CreateEndPropertyCommand(AssociationSetMapping associationSetMapping, AssociationSetEnd associationSetEnd)
     : base(PrereqId)
 {
     AssociationSetMapping = associationSetMapping;
     AssociationSetEnd = associationSetEnd;
 }
 internal static void ValidateAssociationSetMapping(AssociationSetMapping asm)
 {
     ValidateEFElement(asm);
 }
        /// <summary>
        ///     Normalize a refName where the refName is a child of a AssociationSetMapping
        /// </summary>
        /// <param name="asm"></param>
        /// <param name="ep"></param>
        /// <param name="parent"></param>
        /// <param name="refName"></param>
        /// <returns></returns>
        private static NormalizedName NormalizePropertyNameRelativeToAssociationSetMapping(
            AssociationSetMapping asm, EndProperty ep, EFElement parent, string refName)
        {
            NormalizedName nn = null;
            if (ep != null
                && asm != null)
            {
                var prop = parent as ScalarProperty;
                Debug.Assert(prop != null, "parent should be a ScalarProperty");

                if (ep.Name.Status == BindingStatus.Known)
                {
                    nn = NormalizeNameFromAssociationSetEnd(ep.Name.Target, parent, refName);
                }
            }
            return nn;
        }
 internal EnforceAssociationSetMappingRules(CommandProcessorContext cpc, AssociationSetMapping associationSetMapping)
 {
     _cpc = cpc;
     _associationSetMapping = associationSetMapping;
 }
        internal static void AddRule(CommandProcessorContext cpc, AssociationSetMapping associationSetMapping)
        {
            Debug.Assert(associationSetMapping != null, "associationSetMapping should not be null");

            IIntegrityCheck check = new EnforceAssociationSetMappingRules(cpc, associationSetMapping);
            cpc.AddIntegrityCheck(check);
        }
        private EndProperty CloneEndProperty(
            CommandProcessorContext cpc,
            EndProperty endToClone, AssociationSetMapping asmInExistingArtifact, AssociationSetEnd aseInExistingArtifact,
            Dictionary<EntityType, EntityType> tempArtifactCEntityTypeToNewCEntityTypeInExistingArtifact)
        {
            var createEnd = new CreateEndPropertyCommand(asmInExistingArtifact, aseInExistingArtifact);
            CommandProcessor.InvokeSingleCommand(cpc, createEnd);
            var endInExistingArtifact = createEnd.EndProperty;

            if (null == endInExistingArtifact)
            {
                throw new UpdateModelFromDatabaseException(
                    string.Format(
                        CultureInfo.CurrentCulture,
                        Resources.UpdateFromDatabaseCannotCreateAssociationSetMappingEndProperty,
                        aseInExistingArtifact.ToPrettyString()));
            }

            var existingArtifact = cpc.Artifact;
            Debug.Assert(existingArtifact != null, "existingArtifact is null for endToClone " + endToClone.ToPrettyString());

            foreach (var sp in endToClone.ScalarProperties())
            {
                if (null == sp.Name.Target)
                {
                    throw new UpdateModelFromDatabaseException(
                        string.Format(
                            CultureInfo.CurrentCulture,
                            Resources.UpdateFromDatabaseScalarPropertyNoNameTarget,
                            sp.ToPrettyString()));
                }
                if (null == sp.ColumnName.Target)
                {
                    throw new UpdateModelFromDatabaseException(
                        string.Format(
                            CultureInfo.CurrentCulture,
                            Resources.UpdateFromDatabaseScalarPropertyNoColumnNameTarget,
                            sp.ToPrettyString()));
                }

                var spCSideEntityTypeinTempArtifact = sp.Name.Target.EntityType as ConceptualEntityType;
                if (null == spCSideEntityTypeinTempArtifact)
                {
                    throw new UpdateModelFromDatabaseException(
                        string.Format(
                            CultureInfo.CurrentCulture,
                            Resources.UpdateFromDatabaseAssociationSetMappingCannotFindEntityTypeForProperty,
                            sp.Name.Target.ToPrettyString()));
                }

                var spSSideEntityTypeinTempArtifact = sp.ColumnName.Target.EntityType as StorageEntityType;
                if (null == spSSideEntityTypeinTempArtifact)
                {
                    throw new UpdateModelFromDatabaseException(
                        string.Format(
                            CultureInfo.CurrentCulture,
                            Resources.UpdateFromDatabaseAssociationSetMappingCannotFindEntityTypeForProperty,
                            sp.ColumnName.Target.ToPrettyString()));
                }

                var csdlEntityTypeInExistingArtifact =
                    FindMatchingConceptualEntityTypeInExistingArtifact(
                        spCSideEntityTypeinTempArtifact,
                        tempArtifactCEntityTypeToNewCEntityTypeInExistingArtifact);
                if (null == csdlEntityTypeInExistingArtifact)
                {
                    throw new UpdateModelFromDatabaseException(
                        string.Format(
                            CultureInfo.CurrentCulture,
                            Resources.UpdateFromDatabaseAssociationSetMappingCannotFindMatchingEntityType,
                            sp.ToPrettyString(),
                            spCSideEntityTypeinTempArtifact.ToPrettyString()));
                }

                var ssdlEntityTypeInExistingArtifact =
                    FindMatchingStorageEntityTypeInExistingArtifact(spSSideEntityTypeinTempArtifact);
                if (null == ssdlEntityTypeInExistingArtifact)
                {
                    throw new UpdateModelFromDatabaseException(
                        string.Format(
                            CultureInfo.CurrentCulture,
                            Resources.UpdateFromDatabaseAssociationSetMappingCannotFindMatchingEntityType,
                            sp.ToPrettyString(),
                            spSSideEntityTypeinTempArtifact.ToPrettyString()));
                }

                var entityProperty = FindMatchingPropertyInExistingArtifactEntityType(sp.Name.Target, csdlEntityTypeInExistingArtifact);
                if (null == entityProperty)
                {
                    // Cannot find matching property - it must have been unmapped. 
                    // So try to create a new mapped property to which to attach 
                    // this association.

                    // First find S-side Property in temp artifact to which the C-side
                    // Property identified in the AssociationSetMapping is mapped
                    // (Note: cannot use just sp.ColumnName.Target as the S-side Property
                    // used in the AssociationSetMapping can be different from what is used
                    // for the EntitySetMapping in the temp artifact and it is this latter
                    // we need to replicate here).
                    Property sSidePropertyToBeMappedInTempArtifact = null;
                    foreach (var spInTempArtifact in sp.Name.Target.GetAntiDependenciesOfType<ScalarProperty>())
                    {
                        // Ensure that S-side ScalarProperty is from an EntitySetMapping (and not 
                        // an AssociationSetMapping) in the temp artifact.
                        // Can use first one as in temp artifact there is 1:1 mapping.
                        if (null != spInTempArtifact.GetParentOfType(typeof(EntitySetMapping)))
                        {
                            if (null != spInTempArtifact.ColumnName
                                && null != spInTempArtifact.ColumnName.Target)
                            {
                                if (null == sSidePropertyToBeMappedInTempArtifact)
                                {
                                    sSidePropertyToBeMappedInTempArtifact = spInTempArtifact.ColumnName.Target;
                                }
                                else
                                {
                                    // error in temp artifact - there's more than 1 EntitySetMapping ScalarProperty
                                    // mapped to the C-side Property
                                    Debug.Fail(
                                        "C-side Property " + sp.Name.Target.ToPrettyString() +
                                        " has more than 1 ScalarProperty anti-dep with an EntitySetMapping parent. Should be at most 1.");
                                    break;
                                }
                            }
                        }
                    }

                    if (null == sSidePropertyToBeMappedInTempArtifact)
                    {
                        throw new UpdateModelFromDatabaseException(
                            string.Format(
                                CultureInfo.CurrentCulture,
                                Resources.UpdateFromDatabaseAssociationSetMappingCannotFindSSideForCSideProperty,
                                sp.ToPrettyString(),
                                sp.Name.Target.ToPrettyString()));
                    }

                    // Now find the matching S-side Property in the existing artifact
                    var sSidePropertyToBeMappedInExistingArtifact =
                        FindSSidePropInExistingArtifact(sSidePropertyToBeMappedInTempArtifact);
                    if (null == sSidePropertyToBeMappedInExistingArtifact)
                    {
                        throw new UpdateModelFromDatabaseException(
                            string.Format(
                                CultureInfo.CurrentCulture,
                                Resources.UpdateFromDatabaseAssociationSetMappingCannotFindMatchingSSideProperty,
                                sp.ToPrettyString(),
                                sSidePropertyToBeMappedInTempArtifact.ToPrettyString()));
                    }

                    // Now create a new C-side Property in the existing artifact mapped 
                    // to the S-side Property we just found
                    entityProperty = CreateNewConceptualPropertyAndMapping(
                        cpc, sp.Name.Target, sSidePropertyToBeMappedInTempArtifact,
                        csdlEntityTypeInExistingArtifact);
                    if (null == entityProperty)
                    {
                        throw new UpdateModelFromDatabaseException(
                            string.Format(
                                CultureInfo.CurrentCulture,
                                Resources.UpdateFromDatabaseAssociationSetMappingCannotFindOrCreateMatchingProperty,
                                sp.ToPrettyString(),
                                sp.Name.Target.ToPrettyString(),
                                csdlEntityTypeInExistingArtifact.ToPrettyString()));
                    }
                }

                var tableColumn = FindMatchingPropertyInExistingArtifactEntityType(sp.ColumnName.Target, ssdlEntityTypeInExistingArtifact);
                if (null == tableColumn)
                {
                    throw new UpdateModelFromDatabaseException(
                        string.Format(
                            CultureInfo.CurrentCulture,
                            Resources.UpdateFromDatabaseAssociationSetMappingCannotFindMatchingProperty,
                            sp.ToPrettyString(),
                            sp.ColumnName.Target.ToPrettyString(),
                            ssdlEntityTypeInExistingArtifact.ToPrettyString()));
                }

                var createScalar = new CreateEndScalarPropertyCommand(endInExistingArtifact, entityProperty, tableColumn);
                CommandProcessor.InvokeSingleCommand(cpc, createScalar);
                var existingScalarProp = createScalar.ScalarProperty;
                if (null == existingScalarProp)
                {
                    throw new UpdateModelFromDatabaseException(
                        string.Format(
                            CultureInfo.CurrentCulture,
                            Resources.UpdateFromDatabaseCannotCreateAssociationSetMappingScalarProperty,
                            entityProperty.ToPrettyString(),
                            tableColumn.ToPrettyString()));
                }
            }

            return endInExistingArtifact;
        }
        /// <summary>
        ///     Creates a new AssociationSetMapping in the existing EntityContainerMapping
        ///     based on another AssociationSetMapping (asmToClone) in a different artifact.
        ///     All the other parameters are presumed to already exist in the same artifact
        ///     as the EntityContainerMapping.
        /// </summary>
        private AssociationSetMapping CloneAssociationSetMapping(
            CommandProcessorContext cpc, AssociationSetMapping asmToClone,
            EntityContainerMapping existingEntityContainerMapping, AssociationSet existingAssociationSet,
            Association existingAssociation, StorageEntitySet existingStorageEntitySet,
            Dictionary<EntityType, EntityType> tempArtifactCEntityTypeToNewCEntityTypeInExistingArtifact)
        {
            var createASM = new CreateAssociationSetMappingCommand(
                existingEntityContainerMapping, existingAssociationSet, existingAssociation, existingStorageEntitySet);
            CommandProcessor.InvokeSingleCommand(cpc, createASM);
            var asmInExistingArtifact = createASM.AssociationSetMapping;

            if (null == asmInExistingArtifact)
            {
                throw new UpdateModelFromDatabaseException(
                    string.Format(
                        CultureInfo.CurrentCulture,
                        Resources.UpdateFromDatabaseCannotCreateAssociationSetMapping,
                        existingAssociationSet.ToPrettyString()));
            }

            // cannot just look for an AssociationSetEnd with the same Role name in
            // the existing artifact as the role may have changed when the Association was
            // copied into the existing artifact - but we do know the ends were created in 
            // the same order - so simply match them up
            var existingAssocSetEnds = existingAssociationSet.AssociationSetEnds().ToArray();
            if (2 != existingAssocSetEnds.Length)
            {
                throw new UpdateModelFromDatabaseException(
                    string.Format(
                        CultureInfo.CurrentCulture,
                        Resources.UpdateFromDatabaseAssociationSetMappingWrongNumberAssociationSetEnds,
                        existingAssociationSet.ToPrettyString(),
                        existingAssocSetEnds.Length));
            }

            var endsToClone = asmToClone.EndProperties().ToArray();
            if (2 != endsToClone.Length)
            {
                throw new UpdateModelFromDatabaseException(
                    string.Format(
                        CultureInfo.CurrentCulture,
                        Resources.UpdateFromDatabaseAssociationSetMappingWrongNumberAssociationSetEnds,
                        existingAssociationSet.ToPrettyString(),
                        existingAssocSetEnds.Length));
            }

            for (var i = 0; i < 2; i++)
            {
                var aseInExistingArtifact = existingAssocSetEnds[i];
                var endToClone = endsToClone[i];
                CloneEndProperty(
                    cpc, endToClone, asmInExistingArtifact, aseInExistingArtifact, tempArtifactCEntityTypeToNewCEntityTypeInExistingArtifact);
            }

            return asmInExistingArtifact;
        }