コード例 #1
0
        private AssociationSet CreateModelAssociationSet(LoadMethodSessionState session, OneToOneMappingSerializer.CollapsedEntityAssociationSet collapsedAssociationSet)
        {
            // create the association
            string associationName = CreateModelName(collapsedAssociationSet.EntitySet.Name, session.UsedGlobalModelTypeNames);
            AssociationType association = new AssociationType(associationName,
                _namespaceName, false, DataSpace.CSpace);

            // create the association set
            string associationSetName = CreateModelName(collapsedAssociationSet.EntitySet.Name, session.UsedEntityContainerItemNames);
            AssociationSet set = new AssociationSet(associationSetName, association);
            
            // create the association and association set end members
            UniqueIdentifierService usedEndMemberNames = new UniqueIdentifierService(false);
            for(int i = 0; i < collapsedAssociationSet.AssociationSets.Count; i++)
            {
                AssociationSetEnd storeEnd;
                RelationshipMultiplicity multiplicity;
                OperationAction deleteBehavior;
                collapsedAssociationSet.GetStoreAssociationSetEnd(i, out storeEnd, out multiplicity, out deleteBehavior);
                AssociationEndMember end = CreateAssociationEndMember(session, storeEnd.CorrespondingAssociationEndMember, usedEndMemberNames, multiplicity, deleteBehavior);
                association.AddMember(end);

                EntitySet entitySet = session.MappingLookups.StoreEntitySetToModelEntitySet[storeEnd.EntitySet];
                AssociationSetEnd setEnd = new AssociationSetEnd(entitySet, set, end);
                set.AddAssociationSetEnd(setEnd);
                session.MappingLookups.StoreAssociationSetEndToModelAssociationSetEnd.Add(storeEnd, setEnd);
            }

            // don't need a referential constraint

            CreateModelNavigationProperties(session, association);

            collapsedAssociationSet.ModelAssociationSet = set;
           
            return set;
        }
コード例 #2
0
        private AssociationType CreateModelAssociationType(LoadMethodSessionState session, AssociationType storeAssociationType)
        {
            UniqueIdentifierService usedEndMemberNames = new UniqueIdentifierService(false);
            string name = CreateModelName(storeAssociationType.Name, session.UsedGlobalModelTypeNames);

            bool isFkAssociation = false;
            if (_targetEntityFrameworkVersion > EntityFrameworkVersions.Version1)
            {
                isFkAssociation = this.GenerateForeignKeyProperties || RequiresModelReferentialConstraint(storeAssociationType);
            }
            AssociationType association = new AssociationType(name,
                _namespaceName,
                isFkAssociation,
                DataSpace.CSpace);
            KeyValuePair<string, RelationshipMultiplicity> endMultiplicityOverride = CreateEndMultiplicityOverride(session, storeAssociationType, association);

            foreach (AssociationEndMember storeEndMember in storeAssociationType.RelationshipEndMembers)
            {
                AssociationEndMember end = CreateAssociationEndMember(session, storeEndMember, endMultiplicityOverride, usedEndMemberNames);
                session.MappingLookups.StoreAssociationEndMemberToModelAssociationEndMember.Add(storeEndMember, end);
                association.AddMember(end);
            }

            ReferentialConstraint constraint = CreateReferentialConstraint(session, storeAssociationType);
            if (constraint != null)
            {
                association.AddReferentialConstraint(constraint);
            }

            CreateModelNavigationProperties(session, association);

            return association;
        }
コード例 #3
0
        private void CreateAssociationType(LoadMethodSessionState session,
            List<RelationshipDetailsRow> columns)
        {
            Debug.Assert(columns.Count != 0, "should have at least one column");

            RelationshipDetailsRow firstRow = columns[0];

            // get the entity types for the ends
            EntityType pkEntityType;
            EntityType fkEntityType;
            if (!TryGetEndEntities(session, firstRow, out pkEntityType, out fkEntityType))
            {
                return;
            }

            if (!AreRelationshipColumnsTheTypesEntireKey(pkEntityType, columns, r => r.PKColumn))
            {
                session.AddErrorsForType(pkEntityType, new EdmSchemaError(Strings.UnsupportedDbRelationship(firstRow.RelationshipName), (int)ModelBuilderErrorCode.UnsupportedDbRelationship, EdmSchemaErrorSeverity.Warning));
                return;
                         
            }
            UniqueIdentifierService usedEndNames = new UniqueIdentifierService(false);
            // figure out the lower bound of the pk end
            bool someFkColmnsAreNullable;
            if (_targetEntityFrameworkVersion == EntityFrameworkVersions.Version1)
            {
                someFkColmnsAreNullable = AreAllFkKeyColumnsNullable(fkEntityType, columns);
            }
            else
            {
                someFkColmnsAreNullable = AreAnyFkKeyColumnsNullable(fkEntityType, columns);
            }

            RelationshipMultiplicity pkMultiplicity = someFkColmnsAreNullable ? RelationshipMultiplicity.ZeroOrOne : RelationshipMultiplicity.One;
            //Get the Delete Action for the end and set it.
            //The only DeleteAction we support is Cascade, ignor all others for now.
            OperationAction onDeleteAction = OperationAction.None;
            if (firstRow.RelationshipIsCascadeDelete)
            {
                onDeleteAction = OperationAction.Cascade;
            }
            
            AssociationEndMember pkEnd = CreateAssociationEnd( session,
                        pkEntityType,
                        pkMultiplicity,
                        usedEndNames, onDeleteAction);

            RelationshipMultiplicity fkMultiplicity = RelationshipMultiplicity.Many;

            if ( !someFkColmnsAreNullable &&
                 AreRelationshipColumnsTheTypesEntireKey(fkEntityType, columns, r => r.FKColumn))
            {
                // both the pk and fk side columns are the keys of their types
                // so this is a 1 to one relationship
                fkMultiplicity = RelationshipMultiplicity.ZeroOrOne;
            }

            AssociationEndMember fkEnd = CreateAssociationEnd(session, 
                        fkEntityType, 
                        fkMultiplicity,
                        usedEndNames, OperationAction.None);


            // create the type
            string typeName = session.UsedTypeNames.AdjustIdentifier(firstRow.RelationshipName);
            AssociationType type = new AssociationType(typeName, 
                _namespaceName, false, DataSpace.SSpace);
            type.AddMember(pkEnd);
            type.AddMember(fkEnd);

            List<EdmSchemaError> errors = new List<EdmSchemaError>();
            bool isValid = CreateReferentialConstraint(session,
                        type,
                        pkEnd,
                        fkEnd,
                        columns,
                        errors);


            string errorMessage;

            // We can skip most validation checks if the FKs are directly surfaced (since we can produce valid mappings in these cases).
            if (!this.GenerateForeignKeyProperties)
            {
                if (IsFkPartiallyContainedInPK(type, out errorMessage))
                {
                    errors.Add(new EdmSchemaError(
                        errorMessage,
                        (int)ModelBuilderErrorCode.UnsupportedForeinKeyPattern,
                        EdmSchemaErrorSeverity.Warning));
                    isValid = false;
                }

                if (isValid)
                {
                    //Now check if any FK (which could also be a PK) is shared among multiple Associations (ie shared via foreign key constraint).
                    // To do this we check if the Association Type being generated has any dependent property which is also a dependent in one of the association typed already added.
                    //If so, we keep one Association and throw the rest away.

                    foreach (var toPropertyOfAddedAssociation in session.AssociationTypes.SelectMany(t => t.ReferentialConstraints.SelectMany(refconst => refconst.ToProperties)))
                    {
                        foreach (var toProperty in type.ReferentialConstraints.SelectMany(refconst => refconst.ToProperties))
                        {
                            if (toProperty.DeclaringType.Equals(toPropertyOfAddedAssociation.DeclaringType) && toProperty.Equals(toPropertyOfAddedAssociation))
                            {
                                errors.Add(new EdmSchemaError(
                                    Strings.SharedForeignKey(type.Name, toProperty, toProperty.DeclaringType),
                                    (int)ModelBuilderErrorCode.SharedForeignKey,
                                    EdmSchemaErrorSeverity.Warning));

                                isValid = false;
                                break;
                            }
                        }

                        if (!isValid)
                        {
                            break;
                        }
                    }
                }
            }

            if (isValid)
            { 
                session.AssociationTypes.Add(type);
            }
            else
            {
                session.InvalidTypes.Add(type);
                session.RelationshipEndTypeLookup.Remove(pkEnd);
                session.RelationshipEndTypeLookup.Remove(fkEnd);
            }


            type.SetReadOnly();
            session.AddErrorsForType(type, errors);
        }