Ejemplo n.º 1
0
        internal override void Configure(
            AssociationType associationType,
            AssociationEndMember dependentEnd,
            EntityTypeConfiguration entityTypeConfiguration)
        {
            // ISSUE: object of a compiler-generated type is created
            // ISSUE: variable of a compiler-generated type
            ForeignKeyConstraintConfiguration.\u003C\u003Ec__DisplayClasse cDisplayClasse1 = new ForeignKeyConstraintConfiguration.\u003C\u003Ec__DisplayClasse();
            // ISSUE: reference to a compiler-generated field
            cDisplayClasse1.entityTypeConfiguration = entityTypeConfiguration;
            if (!this._dependentProperties.Any <PropertyInfo>())
            {
                return;
            }
            IEnumerable <PropertyInfo> propertyInfos = this._dependentProperties.AsEnumerable <PropertyInfo>();

            if (!this.IsFullySpecified)
            {
                // ISSUE: reference to a compiler-generated field
                if (EntityTypeExtensions.GetClrType(dependentEnd.GetEntityType()) != cDisplayClasse1.entityTypeConfiguration.ClrType)
                {
                    return;
                }
                // ISSUE: reference to a compiler-generated method
                IEnumerable <\u003C\u003Ef__AnonymousType41 <PropertyInfo, int?> > source = this._dependentProperties.Select(new Func <PropertyInfo, \u003C\u003Ef__AnonymousType41 <PropertyInfo, int?> >(cDisplayClasse1.\u003CConfigure\u003Eb__0));
                if (this._dependentProperties.Count > 1 && source.Any(p => !p.ColumnOrder.HasValue))
                {
                    ReadOnlyMetadataCollection <EdmProperty> dependentKeys = dependentEnd.GetEntityType().KeyProperties;
                    if (dependentKeys.Count != this._dependentProperties.Count || !source.All(fk =>
                    {
                        // ISSUE: variable of a compiler-generated type
                        ForeignKeyConstraintConfiguration.\u003C\u003Ec__DisplayClasse cDisplayClasse = cDisplayClasse1;
                        var fk1 = fk;
                        return(dependentKeys.Any <EdmProperty>((Func <EdmProperty, bool>)(p => p.GetClrPropertyInfo().IsSameAs(fk1.PropertyInfo))));
                    }))
                    {
                        // ISSUE: reference to a compiler-generated field
                        throw Error.ForeignKeyAttributeConvention_OrderRequired((object)cDisplayClasse1.entityTypeConfiguration.ClrType);
                    }
                    propertyInfos = dependentKeys.Select <EdmProperty, PropertyInfo>((Func <EdmProperty, PropertyInfo>)(p => p.GetClrPropertyInfo()));
                }
                else
                {
                    propertyInfos = source.OrderBy(p => p.ColumnOrder).Select(p => p.PropertyInfo);
                }
            }
            List <EdmProperty> edmPropertyList = new List <EdmProperty>();

            foreach (PropertyInfo propertyInfo in propertyInfos)
            {
                EdmProperty primitiveProperty = dependentEnd.GetEntityType().GetDeclaredPrimitiveProperty(propertyInfo);
                if (primitiveProperty == null)
                {
                    throw Error.ForeignKeyPropertyNotFound((object)propertyInfo.Name, (object)dependentEnd.GetEntityType().Name);
                }
                edmPropertyList.Add(primitiveProperty);
            }
            AssociationEndMember  otherEnd = associationType.GetOtherEnd(dependentEnd);
            ReferentialConstraint referentialConstraint = new ReferentialConstraint((RelationshipEndMember)otherEnd, (RelationshipEndMember)dependentEnd, (IEnumerable <EdmProperty>)otherEnd.GetEntityType().KeyProperties, (IEnumerable <EdmProperty>)edmPropertyList);

            if (otherEnd.IsRequired())
            {
                referentialConstraint.ToProperties.Each <EdmProperty, bool>((Func <EdmProperty, bool>)(p => p.Nullable = false));
            }
            associationType.Constraint = referentialConstraint;
        }
 /// <summary>
 /// When overriden returns <c>true</c> if <paramref name="dependentProperty"/> should be part of the foreign key.
 /// </summary>
 /// <param name="associationType"> The association type being configured. </param>
 /// <param name="dependentAssociationEnd"> The dependent end. </param>
 /// <param name="dependentProperty"> The candidate property on the dependent end. </param>
 /// <param name="principalEntityType"> The principal end entity type. </param>
 /// <param name="principalKeyProperty"> A key property on the principal end that is a candidate target for the foreign key. </param>
 /// <returns>true if dependentProperty should be a part of the foreign key; otherwise, false.</returns>
 protected abstract bool MatchDependentKeyProperty(
     AssociationType associationType,
     AssociationEndMember dependentAssociationEnd,
     EdmProperty dependentProperty,
     EntityType principalEntityType,
     EdmProperty principalKeyProperty);
Ejemplo n.º 3
0
        private List <ModelBidirectionalAssociation> GetBidirectionalAssociations(EntityType entityType)
        {
            List <ModelBidirectionalAssociation> result = new List <ModelBidirectionalAssociation>();

            if (entityType == null)
            {
                return(result);
            }

            foreach (NavigationProperty navigationProperty in entityType.DeclaredNavigationProperties.Where(np => Inverse(np) != null))
            {
                StructuralType sourceType = navigationProperty.DeclaringType;

                if (sourceType.Name != entityType.Name)
                {
                    continue;
                }

                ModelBidirectionalAssociation association = new ModelBidirectionalAssociation();
                EntityType targetType = navigationProperty.ToEndMember.GetEntityType();

                AssociationType       associationType = navigationProperty.RelationshipType as AssociationType;
                ReferentialConstraint constraint      = associationType?.Constraint;
                AssociationEndMember  principalEnd    = constraint?.FromRole as AssociationEndMember;
                EntityType            principalType   = principalEnd?.GetEntityType();

                AssociationEndMember dependentEnd  = constraint?.ToRole as AssociationEndMember;
                EntityType           dependentType = dependentEnd?.GetEntityType();

                if (principalType?.Name == sourceType.Name)
                {
                    association.SourceRole = AssociationRole.Principal;
                    association.TargetRole = AssociationRole.Dependent;
                }
                else if (principalType?.Name == targetType.Name)
                {
                    association.TargetRole = AssociationRole.Principal;
                    association.SourceRole = AssociationRole.Dependent;
                }
                else if (principalType == null && dependentType == null)
                {
                    association.SourceRole = AssociationRole.NotApplicable;
                    association.TargetRole = AssociationRole.NotApplicable;
                }

                association.SourceClassName      = sourceType.Name;
                association.SourceClassNamespace = sourceType.NamespaceName;
                association.TargetClassName      = targetType.Name;
                association.TargetClassNamespace = targetType.NamespaceName;

                NavigationProperty inverse = Inverse(navigationProperty);

                // the property in the source class (referencing the target class)
                association.TargetPropertyTypeName = targetType.Name;
                association.TargetPropertyName     = navigationProperty.Name;
                association.TargetMultiplicity     = ConvertMultiplicity(navigationProperty.ToEndMember.RelationshipMultiplicity);
                association.TargetSummary          = navigationProperty.ToEndMember.Documentation?.Summary;
                association.TargetDescription      = navigationProperty.ToEndMember.Documentation?.LongDescription;

                // the property in the target class (referencing the source class)
                association.SourcePropertyTypeName = navigationProperty.FromEndMember.GetEntityType().Name;
                association.SourcePropertyName     = inverse?.Name;
                association.SourceMultiplicity     = ConvertMultiplicity(navigationProperty.FromEndMember.RelationshipMultiplicity);
                association.SourceSummary          = navigationProperty.FromEndMember.Documentation?.Summary;
                association.SourceDescription      = navigationProperty.FromEndMember.Documentation?.LongDescription;

                // look for declared foreign keys
                List <EdmProperty> dependentProperties = navigationProperty.GetDependentProperties().ToList();

                if (dependentProperties.Any())
                {
                    association.ForeignKey = string.Join(",", dependentProperties.Select(p => p.Name));
                }

                log.Debug($"Found bidirectional association {association.SourceClassName}.{association.TargetPropertyName} <-> {association.TargetClassName}.{association.SourcePropertyTypeName}");
                log.Debug("\n   " + JsonConvert.SerializeObject(association));
                result.Add(association);
            }

            return(result);
        }
        private static Func <RelationshipManager, RelatedEnd, RelatedEnd> CreateGetRelatedEndMethod <TSource, TTarget>(AssociationEndMember sourceMember, AssociationEndMember targetMember, NavigationPropertyAccessor sourceAccessor, NavigationPropertyAccessor targetAccessor)
            where TSource : class
            where TTarget : class
        {
            Func <RelationshipManager, RelatedEnd, RelatedEnd> getRelatedEnd;

            // Get the appropriate method, either collection or reference depending on the target multiplicity
            switch (targetMember.RelationshipMultiplicity)
            {
            case RelationshipMultiplicity.ZeroOrOne:
            case RelationshipMultiplicity.One:
            {
                getRelatedEnd = (manager, relatedEnd) =>
                                manager.GetRelatedReference <TSource, TTarget>(sourceMember.DeclaringType.FullName,
                                                                               sourceMember.Name,
                                                                               targetMember.Name,
                                                                               sourceAccessor,
                                                                               targetAccessor,
                                                                               sourceMember.RelationshipMultiplicity,
                                                                               relatedEnd);

                break;
            }

            case RelationshipMultiplicity.Many:
            {
                getRelatedEnd = (manager, relatedEnd) =>
                                manager.GetRelatedCollection <TSource, TTarget>(sourceMember.DeclaringType.FullName,
                                                                                sourceMember.Name,
                                                                                targetMember.Name,
                                                                                sourceAccessor,
                                                                                targetAccessor,
                                                                                sourceMember.RelationshipMultiplicity,
                                                                                relatedEnd);

                break;
            }

            default:
                throw EntityUtil.InvalidEnumerationValue(typeof(RelationshipMultiplicity), (int)targetMember.RelationshipMultiplicity);
            }

            return(getRelatedEnd);
        }
Ejemplo n.º 5
0
 internal abstract void Configure(
     AssociationType associationType, AssociationEndMember dependentEnd,
     EntityTypeConfiguration entityTypeConfiguration);
 // <summary>
 // Construct a new AssociationEnd member mapping metadata object
 // </summary>
 internal ObjectAssociationEndMapping(AssociationEndMember edmAssociationEnd, AssociationEndMember clrAssociationEnd)
     : base(edmAssociationEnd, clrAssociationEnd)
 {
 }
                internal DirectionalRelationship(EntityKey toEntityKey, AssociationEndMember fromEnd, AssociationEndMember toEnd, AssociationSet associationSet, IEntityStateEntry stateEntry)
                {
                    ToEntityKey    = EntityUtil.CheckArgumentNull(toEntityKey, "toEntityKey");
                    FromEnd        = EntityUtil.CheckArgumentNull(fromEnd, "fromEnd");
                    ToEnd          = EntityUtil.CheckArgumentNull(toEnd, "toEnd");
                    AssociationSet = EntityUtil.CheckArgumentNull(associationSet, "associationSet");
                    StateEntry     = EntityUtil.CheckArgumentNull(stateEntry, "stateEntry");
                    _equivalenceSetLinkedListNext = this;

                    _hashCode = toEntityKey.GetHashCode() ^
                                fromEnd.GetHashCode() ^
                                toEnd.GetHashCode() ^
                                associationSet.GetHashCode();
                }
Ejemplo n.º 8
0
        internal override void Configure(
            AssociationType associationType,
            AssociationEndMember dependentEnd,
            EntityTypeConfiguration entityTypeConfiguration)
        {
            DebugCheck.NotNull(associationType);
            DebugCheck.NotNull(dependentEnd);
            DebugCheck.NotNull(entityTypeConfiguration);

            if (!_dependentProperties.Any())
            {
                return;
            }

            var dependentPropertInfos = _dependentProperties.AsEnumerable();

            if (!IsFullySpecified)
            {
                var foreignKeys
                    = from p in _dependentProperties
                      select new
                    {
                    PropertyInfo = p,
                    entityTypeConfiguration.Property(new PropertyPath(p)).ColumnOrder
                    };

                if ((_dependentProperties.Count > 1) &&
                    foreignKeys.Any(p => !p.ColumnOrder.HasValue))
                {
                    var dependentKeys = dependentEnd.GetEntityType().KeyProperties;

                    if ((dependentKeys.Count == _dependentProperties.Count) &&
                        foreignKeys.All(fk => dependentKeys.Any(p => p.GetClrPropertyInfo().IsSameAs(fk.PropertyInfo))))
                    {
                        // The FK and PK sets are equal, we know the order
                        dependentPropertInfos = dependentKeys.Select(p => p.GetClrPropertyInfo());
                    }
                    else
                    {
                        throw Error.ForeignKeyAttributeConvention_OrderRequired(entityTypeConfiguration.ClrType);
                    }
                }
                else
                {
                    dependentPropertInfos = foreignKeys.OrderBy(p => p.ColumnOrder).Select(p => p.PropertyInfo);
                }
            }

            var dependentProperties = new List <EdmProperty>();

            foreach (var dependentProperty in dependentPropertInfos)
            {
                var property
                    = dependentEnd.GetEntityType()
                      .GetDeclaredPrimitiveProperty(dependentProperty);

                if (property == null)
                {
                    throw Error.ForeignKeyPropertyNotFound(
                              dependentProperty.Name, dependentEnd.GetEntityType().Name);
                }

                dependentProperties.Add(property);
            }

            var principalEnd = associationType.GetOtherEnd(dependentEnd);

            var associationConstraint
                = new ReferentialConstraint(
                      principalEnd,
                      dependentEnd,
                      principalEnd.GetEntityType().KeyProperties,
                      dependentProperties);

            if (principalEnd.IsRequired())
            {
                associationConstraint.ToProperties.Each(p => p.Nullable = false);
            }

            associationType.Constraint = associationConstraint;
        }
        // effects: Ensures that there is a relationship mapped into the C-space for some cell in m_cellGroup. Else
        // adds an error to errorLog
        private void GuaranteeMappedRelationshipForForeignKey(QueryRewriter childRewriter, QueryRewriter parentRewriter,
                                                              IEnumerable <Cell> cells,
                                                              ErrorLog errorLog, ConfigViewGenerator config)
        {
            ViewgenContext childContext  = childRewriter.ViewgenContext;
            ViewgenContext parentContext = parentRewriter.ViewgenContext;

            // Find a cell where this foreign key is mapped as a relationship
            MemberPath prefix     = new MemberPath(ChildTable);
            ExtentKey  primaryKey = ExtentKey.GetPrimaryKeyForEntityType(prefix, ChildTable.ElementType);
            IEnumerable <MemberPath> primaryKeyFields = primaryKey.KeyFields;
            bool foundCell = false;

            bool foundValidParentColumnsForForeignKey = false; //we need to find only one, dont error on any one check being false
            List <ErrorLog.Record> errorListForInvalidParentColumnsForForeignKey = null;

            foreach (Cell cell in cells)
            {
                if (cell.SQuery.Extent.Equals(ChildTable) == false)
                {
                    continue;
                }

                // The childtable is mapped to a relationship in the C-space in cell
                // Check that all the columns of the foreign key and the primary key in the child table are mapped to some
                // property in the C-space

                AssociationEndMember parentEnd = GetRelationEndForColumns(cell, ChildColumns);
                if (parentEnd != null && CheckParentColumnsForForeignKey(cell, cells, parentEnd, ref errorListForInvalidParentColumnsForForeignKey) == false)
                {
                    // Not an error unless we find no valid case
                    continue;
                }
                else
                {
                    foundValidParentColumnsForForeignKey = true;
                }

                AssociationEndMember childEnd = GetRelationEndForColumns(cell, primaryKeyFields);
                Debug.Assert(childEnd == null || parentEnd != childEnd,
                             "Ends are same => PKey and child columns are same - code should gone to other method");
                // Note: If both of them are not-null, they are mapped to the
                // same association set -- since we checked that particular cell

                if (childEnd != null && parentEnd != null &&
                    FindEntitySetForColumnsMappedToEntityKeys(cells, primaryKeyFields) != null)
                {
                    foundCell = true;
                    CheckConstraintWhenParentChildMapped(cell, errorLog, parentEnd, config);
                    break; // Done processing for the foreign key - either it was mapped correctly or it was not
                }
                else if (parentEnd != null)
                {
                    // At this point, we know cell corresponds to an association set
                    AssociationSet assocSet  = (AssociationSet)cell.CQuery.Extent;
                    EntitySet      parentSet = MetadataHelper.GetEntitySetAtEnd(assocSet, parentEnd);
                    foundCell = CheckConstraintWhenOnlyParentMapped(cell, parentSet, assocSet, parentEnd, childRewriter, parentRewriter, config);
                    if (foundCell)
                    {
                        break;
                    }
                }
            }

            //CheckParentColumnsForForeignKey has returned no matches, Error.
            if (!foundValidParentColumnsForForeignKey)
            {
                Debug.Assert(errorListForInvalidParentColumnsForForeignKey != null && errorListForInvalidParentColumnsForForeignKey.Count > 0);
                foreach (var errorRecord in errorListForInvalidParentColumnsForForeignKey)
                {
                    errorLog.AddEntry(errorRecord);
                }
                return;
            }

            if (foundCell == false)
            {
                // No cell found -- Declare error
                string message = System.Data.Entity.Strings.ViewGen_Foreign_Key_Missing_Relationship_Mapping(ToUserString());

                IEnumerable <LeftCellWrapper> parentWrappers     = GetWrappersFromContext(parentContext, ParentTable);
                IEnumerable <LeftCellWrapper> childWrappers      = GetWrappersFromContext(childContext, ChildTable);
                Set <LeftCellWrapper>         bothExtentWrappers =
                    new Set <LeftCellWrapper>(parentWrappers);
                bothExtentWrappers.AddRange(childWrappers);
                ErrorLog.Record record = new ErrorLog.Record(true, ViewGenErrorCode.ForeignKeyMissingRelationshipMapping, message, bothExtentWrappers, String.Empty);
                errorLog.AddEntry(record);
            }
        }
Ejemplo n.º 10
0
        public void BuildAssociationSetMappings_builds_conceptual_association_set_mapping_for_collapsed_store_entity_sets()
        {
            #region Setting up many to many relationship in the SSpace Teacher * -- 1 TeacherStudents 1 -- * Teachers

            var joinStoreEntityType =
                EntityType.Create(
                    "TeacherStudents", "ns.Store", DataSpace.SSpace,
                    new[] { "JoinTeacherId", "JoinStudentId" },
                    new[]
            {
                CreateStoreProperty("JoinTeacherId", "int"),
                CreateStoreProperty("JoinStudentId", "int")
            }, null);

            var joinStoreEntitySet =
                EntitySet.Create("TeacherStudentsSet", "dbo", "TeacherStudentTable", null, joinStoreEntityType, null);

            var storeTeacherEntityType =
                EntityType.Create(
                    "Teacher", "ns.Store", DataSpace.SSpace, new[] { "TeacherId" },
                    new[] { CreateStoreProperty("TeacherId", "int") }, null);
            var storeTeacherEntitySet =
                EntitySet.Create("TeachersSet", "dbo", "Teachers", null, storeTeacherEntityType, null);

            var storeStudentEntityType =
                EntityType.Create(
                    "Student", "ns.Store", DataSpace.SSpace, new[] { "StudentId" },
                    new[] { CreateStoreProperty("StudentId", "int") }, null);
            var storeStudentEntitySet =
                EntitySet.Create("StudentSet", "dbo", "Students", null, storeStudentEntityType, null);

            var storeTeachersEndMember =
                AssociationEndMember.Create(
                    "Teachers", storeTeacherEntityType.GetReferenceType(), RelationshipMultiplicity.Many,
                    OperationAction.None, null);

            var storeTeacherStudentsfromTeachersEndMember =
                AssociationEndMember.Create(
                    "TeacherStudents_fromTeachers", joinStoreEntityType.GetReferenceType(), RelationshipMultiplicity.One,
                    OperationAction.None, null);

            var storeTeacherAssociationType =
                AssociationType.Create(
                    "Teacher_TeacherStudentsAssociationType", "ns.Store", false, DataSpace.SSpace,
                    storeTeachersEndMember, storeTeacherStudentsfromTeachersEndMember,
                    new ReferentialConstraint(
                        storeTeachersEndMember, storeTeacherStudentsfromTeachersEndMember, storeTeacherEntityType.KeyProperties,
                        joinStoreEntityType.KeyProperties.Where(p => p.Name == "JoinTeacherId")),
                    null);

            var storeTeacherAssociationSet =
                AssociationSet.Create(
                    "Teacher_TeacherStudents", storeTeacherAssociationType, storeTeacherEntitySet, joinStoreEntitySet, null);

            var storeStudentsEndMember =
                AssociationEndMember.Create(
                    "Students", storeStudentEntityType.GetReferenceType(), RelationshipMultiplicity.Many,
                    OperationAction.None, null);

            var storeTeacherStudentsfromStudentsEndMember =
                AssociationEndMember.Create(
                    "TeacherStudents_fromStudents", joinStoreEntityType.GetReferenceType(), RelationshipMultiplicity.One,
                    OperationAction.None, null);

            var storeStudentAssociationType =
                AssociationType.Create(
                    "Student_TeacherStudentsAssociationType", "ns.Store", false, DataSpace.SSpace,
                    storeStudentsEndMember,
                    storeTeacherStudentsfromStudentsEndMember,
                    new ReferentialConstraint(
                        storeStudentsEndMember, storeTeacherStudentsfromStudentsEndMember, storeStudentEntityType.KeyProperties,
                        joinStoreEntityType.KeyProperties.Where(p => p.Name == "JoinStudentId")),
                    null);

            var storeStudentAssociationSet =
                AssociationSet.Create(
                    "Student_TeacherStudents", storeStudentAssociationType, storeStudentEntitySet, joinStoreEntitySet, null);

            var collapsedAssociationSet = new CollapsibleEntityAssociationSets(joinStoreEntitySet);
            collapsedAssociationSet.AssociationSets.Add(storeTeacherAssociationSet);
            collapsedAssociationSet.AssociationSets.Add(storeStudentAssociationSet);

            #endregion

            #region Setting up many to many relationship in the CSpace Teacher * -- * Teachers

            var conceptualContainer = EntityContainer.Create("ConceptualContainer", DataSpace.CSpace, null, null, null);

            var edmIntTypeUsage =
                TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32));

            var conceptualTeacherEntityType =
                EntityType.Create(
                    "Teacher", "ns", DataSpace.CSpace, new[] { "TeacherId" },
                    new[] { EdmProperty.Create("TeacherId", edmIntTypeUsage) }, null);

            var conceptualTeacherEntitySet =
                EntitySet.Create("TeachersSet", null, null, null, conceptualTeacherEntityType, null);

            var conceptualStudentEntityType =
                EntityType.Create(
                    "Student", "ns", DataSpace.CSpace, new[] { "StudentId" },
                    new[] { EdmProperty.Create("StudentId", edmIntTypeUsage) }, null);

            var conceptualStudentEntitySet =
                EntitySet.Create("StudentSet", "dbo", "Students", null, conceptualStudentEntityType, null);

            var conceptualTeachersEndMember =
                AssociationEndMember.Create(
                    "TeachersEnd", conceptualTeacherEntityType.GetReferenceType(), RelationshipMultiplicity.Many,
                    OperationAction.None, null);

            var conceptualStudentsEndMember =
                AssociationEndMember.Create(
                    "StudentsEnd", conceptualStudentEntityType.GetReferenceType(), RelationshipMultiplicity.Many,
                    OperationAction.None, null);

            var conceptualAssociationType =
                AssociationType.Create(
                    "TeacherStudentAssociation",
                    "ns.Model",
                    false,
                    DataSpace.CSpace,
                    conceptualTeachersEndMember,
                    conceptualStudentsEndMember,
                    new ReferentialConstraint(
                        conceptualTeachersEndMember, conceptualStudentsEndMember,
                        conceptualTeacherEntityType.KeyProperties, conceptualStudentEntityType.KeyProperties),
                    null);

            var conceptualAssociationSet =
                AssociationSet.Create(
                    "TeacherStudentSet", conceptualAssociationType, conceptualTeacherEntitySet,
                    conceptualStudentEntitySet, null);

            #endregion

            var mappingContext = new SimpleMappingContext(new EdmModel(DataSpace.SSpace), true);
            mappingContext.AddMapping(collapsedAssociationSet, conceptualAssociationSet);
            mappingContext.AddMapping(storeTeachersEndMember, conceptualTeachersEndMember);
            mappingContext.AddMapping(storeStudentsEndMember, conceptualStudentsEndMember);
            mappingContext.AddMapping(
                storeTeacherAssociationSet.AssociationSetEnds.ElementAt(0),
                conceptualAssociationSet.AssociationSetEnds.ElementAt(0));
            mappingContext.AddMapping(
                storeStudentAssociationSet.AssociationSetEnds.ElementAt(0),
                conceptualAssociationSet.AssociationSetEnds.ElementAt(1));
            mappingContext.AddMapping(
                storeStudentEntityType.KeyProperties.Single(), conceptualStudentEntityType.KeyProperties.Single());
            mappingContext.AddMapping(
                storeTeacherEntityType.KeyProperties.Single(), conceptualTeacherEntityType.KeyProperties.Single());

            var storageEntitySetMapping =
                new EntityContainerMapping(conceptualContainer, null, null, false, false);

            var associationSetMapping =
                DbDatabaseMappingBuilder.BuildAssociationSetMappings(storageEntitySetMapping, mappingContext)
                .SingleOrDefault();
            Assert.NotNull(associationSetMapping);

            var mappingFragment = associationSetMapping.TypeMappings.SingleOrDefault();
            Assert.NotNull(mappingFragment);

            var propertyMappings = mappingFragment.MappingFragments.Single().PropertyMappings;
            Assert.Equal(2, propertyMappings.Count);
            Assert.Same(conceptualTeachersEndMember, ((EndPropertyMapping)propertyMappings[0]).AssociationEnd);
            Assert.Same(conceptualStudentsEndMember, ((EndPropertyMapping)propertyMappings[1]).AssociationEnd);

            var scalarPropertyMapping = ((EndPropertyMapping)propertyMappings[0]).PropertyMappings.Single();
            Assert.Same(conceptualTeacherEntityType.KeyMembers.Single(), scalarPropertyMapping.Property);
            Assert.Same(
                joinStoreEntityType.KeyMembers.Single(m => m.Name == "JoinTeacherId"),
                scalarPropertyMapping.Column);

            scalarPropertyMapping = ((EndPropertyMapping)propertyMappings[1]).PropertyMappings.Single();
            Assert.Same(conceptualStudentEntityType.KeyMembers.Single(), scalarPropertyMapping.Property);
            Assert.Same(
                joinStoreEntityType.KeyMembers.Single(m => m.Name == "JoinStudentId"),
                scalarPropertyMapping.Column);
        }
Ejemplo n.º 11
0
 protected virtual void Visit(AssociationEndMember associationEndMember)
 {
     Visit(associationEndMember.TypeUsage);
 }
        public void Can_configure_ia_fk_parameters()
        {
            var modificationFunctionConfiguration = new ModificationFunctionConfiguration();

            var mockPropertyInfo1 = new MockPropertyInfo();
            var mockPropertyInfo2 = new MockPropertyInfo();

            modificationFunctionConfiguration
            .Parameter(new PropertyPath(new[] { mockPropertyInfo1.Object, mockPropertyInfo2.Object }), "Foo");

            var entitySet = new EntitySet();

            entitySet.ChangeEntityContainerWithoutCollectionFixup(new EntityContainer("C", DataSpace.CSpace));

            var property1 = new EdmProperty("P1");

            property1.SetClrPropertyInfo(mockPropertyInfo1);

            var function           = new EdmFunction("F", "N", DataSpace.SSpace);
            var functionParameter1 = new FunctionParameter();

            var associationType = new AssociationType("A", XmlConstants.ModelNamespace_3, false, DataSpace.CSpace);

            var associationEndMember1
                = new AssociationEndMember("AE1", new EntityType("E", "N", DataSpace.CSpace))
                {
                RelationshipMultiplicity = RelationshipMultiplicity.Many
                };

            var associationEndMember2
                = new AssociationEndMember("AE2", new EntityType("E", "N", DataSpace.CSpace))
                {
                RelationshipMultiplicity = RelationshipMultiplicity.One
                };

            associationEndMember2.SetClrPropertyInfo(mockPropertyInfo1);

            associationType.SourceEnd = associationEndMember1;
            associationType.TargetEnd = associationEndMember2;

            var associationSet = new AssociationSet("AS", associationType);

            associationSet.AddAssociationSetEnd(
                new AssociationSetEnd(entitySet, associationSet, associationEndMember2));

            modificationFunctionConfiguration.Configure(
                new StorageModificationFunctionMapping(
                    entitySet,
                    new EntityType("E", "N", DataSpace.CSpace),
                    function,
                    new[]
            {
                new StorageModificationFunctionParameterBinding(
                    functionParameter1,
                    new StorageModificationFunctionMemberPath(
                        new EdmMember[] { property1, associationEndMember2 },
                        associationSet),
                    false)
            },
                    null,
                    null),
                ProviderRegistry.Sql2008_ProviderManifest);

            Assert.Equal("Foo", functionParameter1.Name);
        }
        public void Can_configure_function_name_and_parameters()
        {
            var modificationFunctionConfiguration = new ModificationFunctionConfiguration();

            modificationFunctionConfiguration.HasName("Foo", "Bar");

            var mockPropertyInfo1 = new MockPropertyInfo();
            var mockPropertyInfo2 = new MockPropertyInfo();

            modificationFunctionConfiguration
            .Parameter(new PropertyPath(mockPropertyInfo1), "Foo");

            modificationFunctionConfiguration
            .Parameter(new PropertyPath(new[] { mockPropertyInfo1.Object, mockPropertyInfo2.Object }), "Bar");

            var entitySet = new EntitySet();

            entitySet.ChangeEntityContainerWithoutCollectionFixup(new EntityContainer("C", DataSpace.CSpace));

            var property1 = new EdmProperty("P1");

            property1.SetClrPropertyInfo(mockPropertyInfo1);

            var property2 = new EdmProperty("P1");

            property2.SetClrPropertyInfo(mockPropertyInfo2);

            var functionParameter1
                = new FunctionParameter(
                      "P1",
                      TypeUsage.Create(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String)),
                      ParameterMode.In);

            var functionParameter2
                = new FunctionParameter(
                      "P2",
                      TypeUsage.Create(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String)),
                      ParameterMode.In);

            var functionParameter3
                = new FunctionParameter(
                      "Foo",
                      TypeUsage.Create(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String)),
                      ParameterMode.In);

            var function
                = new EdmFunction(
                      "F", "N", DataSpace.SSpace,
                      new EdmFunctionPayload
            {
                Parameters = new[] { functionParameter1, functionParameter2, functionParameter3 }
            });

            var associationType = new AssociationType("A", XmlConstants.ModelNamespace_3, false, DataSpace.CSpace);

            var associationEndMember1
                = new AssociationEndMember("AE1", new EntityType("E", "N", DataSpace.CSpace))
                {
                RelationshipMultiplicity = RelationshipMultiplicity.Many
                };

            var associationEndMember2
                = new AssociationEndMember("AE2", new EntityType("E", "N", DataSpace.CSpace))
                {
                RelationshipMultiplicity = RelationshipMultiplicity.Many
                };

            associationType.SourceEnd = associationEndMember1;
            associationType.TargetEnd = associationEndMember2;

            var associationSet = new AssociationSet("AS", associationType);

            associationSet.AddAssociationSetEnd(
                new AssociationSetEnd(entitySet, associationSet, associationEndMember2));

            modificationFunctionConfiguration.Configure(
                new StorageModificationFunctionMapping(
                    entitySet,
                    new EntityType("E", "N", DataSpace.CSpace),
                    function,
                    new[]
            {
                new StorageModificationFunctionParameterBinding(
                    functionParameter1,
                    new StorageModificationFunctionMemberPath(
                        new EdmMember[] { property1, associationEndMember2 },
                        associationSet),
                    false),
                new StorageModificationFunctionParameterBinding(
                    functionParameter2,
                    new StorageModificationFunctionMemberPath(
                        new[] { property1, property2 },
                        null),
                    false)
            },
                    null,
                    null),
                ProviderRegistry.Sql2008_ProviderManifest);

            Assert.Equal("Foo", function.StoreFunctionNameAttribute);
            Assert.Equal("Bar", function.Schema);
            Assert.Equal("Foo", functionParameter1.Name);
            Assert.Equal("Bar", functionParameter2.Name);
            Assert.Equal("Foo1", functionParameter3.Name);
        }
Ejemplo n.º 14
0
        internal static EntityType GetEntityType(AssociationEndMember end)
        {
            EntityType entityType = (EntityType)((RefType)end.TypeUsage.EdmType).ElementType;

            return(entityType);
        }
Ejemplo n.º 15
0
 /// <summary>
 /// Initializes a new instance of AssocationSetEnd
 /// </summary>
 /// <param name="entitySet">Entity set that this end refers to</param>
 /// <param name="parentSet">The association set which this belongs to</param>
 /// <param name="endMember">The end member of the association set which this is an instance of</param>
 /// <exception cref="System.ArgumentNullException">Thrown if either the role,entitySet, parentSet or endMember arguments are null </exception>
 internal AssociationSetEnd(EntitySet entitySet, AssociationSet parentSet, AssociationEndMember endMember)
 {
     _entitySet = EntityUtil.GenericCheckArgumentNull(entitySet, "entitySet");
     _parentSet = EntityUtil.GenericCheckArgumentNull(parentSet, "parentSet");
     _endMember = EntityUtil.GenericCheckArgumentNull(endMember, "endMember");
 }
        // requires: IsForeignKeySuperSetOfPrimaryKeyInChildTable() is false
        // and primaryKeys of ChildTable are not mapped in cell. cell
        // corresponds to an association set. parentSet is the set
        // corresponding to the end that we are looking at
        // effects: Checks if the constraint is correctly maintained in
        // C-space via an association set (being a subset of the
        // corresponding entitySet)
        private bool CheckConstraintWhenOnlyParentMapped(Cell cell, EntitySet parentSet, AssociationSet assocSet, AssociationEndMember endMember,
                                                         QueryRewriter childRewriter, QueryRewriter parentRewriter,
                                                         ConfigViewGenerator config)
        {
            ViewgenContext childContext  = childRewriter.ViewgenContext;
            ViewgenContext parentContext = parentRewriter.ViewgenContext;

            CellTreeNode pNode = parentRewriter.BasicView;

            Debug.Assert(pNode != null);

            RoleBoolean endRoleBoolean = new RoleBoolean(assocSet.AssociationSetEnds[endMember.Name]);
            // use query in pNode as a factory to create a bool expression for the endRoleBoolean
            BoolExpression endCondition = pNode.RightFragmentQuery.Condition.Create(endRoleBoolean);
            FragmentQuery  cNodeQuery   = FragmentQuery.Create(pNode.RightFragmentQuery.Attributes, endCondition);

            FragmentQueryProcessor qp = FragmentQueryProcessor.Merge(childContext.RightFragmentQP, parentContext.RightFragmentQP);
            bool cImpliesP            = qp.IsContainedIn(cNodeQuery, pNode.RightFragmentQuery);

            return(cImpliesP);
        }
Ejemplo n.º 17
0
        // <summary>
        // Determines whether the specified { from, to } relationship end pairing represents a navigation that is
        // valid for a relationship span sourced by an instance of the specified entity type.
        // </summary>
        // <param name="compareType"> The Entity type which valid 'from' ends must reference (or a supertype of that Entity type) </param>
        // <param name="associationType"> The Association type to consider. </param>
        // <param name="fromEnd"> The candidate 'from' end, which will be checked based on the Entity type it references </param>
        // <param name="toEnd"> The candidate 'to' end, which will be checked base on the upper bound of its multiplicity </param>
        // <returns>
        // <c>True</c> if the end pairing represents a valid navigation from an instance of the specified entity type to an association end with a multiplicity upper bound of at most 1; otherwise <c>false</c>
        // </returns>
        private static bool IsValidRelationshipSpan(
            EntityType compareType, AssociationType associationType, AssociationEndMember fromEnd, AssociationEndMember toEnd)
        {
            // Only a relationship end with a multiplicity of AT MOST one may be
            // considered as the 'to' end, so that the cardinality of the result
            // of the relationship span has an upper bound of 1.
            // Therefore ends with RelationshipMultiplicity of EITHER One OR ZeroOrOne
            // are the only ends that should be considered as target ends.
            // Note that a relationship span can be sourced by an Entity that is of the same type
            // as the Entity type referenced by the 'from' end OR any type in the same branch of
            // the type hierarchy.
            //
            // For example, in the following hierarchy:
            //
            // A  (*<-->?) AOwner
            // |_B  (*<-->1) BOwner
            // |_A1  (*<-->?) A1Owner
            //   |_A2
            //     |_A3_1  (1<-->?) A3_1Owner
            //     |_A3_2  (*<-->1) A3_2Owner
            //
            // An instance of 'A' would need ALL the 'AOwner', 'BOwner', 'A1Owner', 'A3_1Owner' and 'A3_2Owner' ends
            // spanned in because an instance of 'A' could actually be an instance of A, B, A1, A2, A3_1 or A3_2.
            // An instance of 'B' would only need 'AOwner' and 'BOwner' spanned in.
            // An instance of A2 would need 'AOwner', 'A1Owner', 'A3_1Owner' and 'A3_2Owner' spanned in.
            // An instance of A3_1 would only need 'AOwner', 'A1Owner' and 'A3_1Owner' spanned in.
            //
            // In general, the rule for relationship span is:
            // - 'To' end cardinality AT MOST one
            //   AND
            //   - Referenced Entity type of 'From' end is equal to instance Entity type
            //     OR
            //   - Referenced Entity type of 'From' end is a supertype of instance Entity type
            //     OR
            //   - Referenced Entity type of 'From' end is a subtype of instance Entity type
            //     (this follows from the fact that an instance of 'A' may be an instance of any of its derived types.
            //      Navigation for a subtype relationship will return null if the Entity instance navigation source
            //      is not actually of the required subtype).
            //
            if (!associationType.IsForeignKey
                &&
                (RelationshipMultiplicity.One == toEnd.RelationshipMultiplicity ||
                 RelationshipMultiplicity.ZeroOrOne == toEnd.RelationshipMultiplicity))
            {
                var fromEntityType = (EntityType)((RefType)fromEnd.TypeUsage.EdmType).ElementType;
                return(EntityTypeEquals(compareType, fromEntityType) ||
                       TypeSemantics.IsSubTypeOf(compareType, fromEntityType) ||
                       TypeSemantics.IsSubTypeOf(fromEntityType, compareType));
            }

            return(false);
        }
        // effects: Given the foreign key constraint, checks if the
        // constraint.ParentColumns are mapped to the entity set E'e keys in
        // C-space where E corresponds to the entity set corresponding to end
        // Returns true iff such a mapping exists in cell
        private bool CheckParentColumnsForForeignKey(Cell cell, IEnumerable <Cell> cells, AssociationEndMember parentEnd, ref List <ErrorLog.Record> errorList)
        {
            // The child columns are mapped to some end of cell.CQuery.Extent. ParentColumns
            // must correspond to the EntitySet for this end
            AssociationSet relationSet = (AssociationSet)cell.CQuery.Extent;
            EntitySet      endSet      = MetadataHelper.GetEntitySetAtEnd(relationSet, parentEnd);

            // Check if the ParentColumns are mapped to endSet's keys

            // Find the entity set that they map to - if any
            EntitySet entitySet = FindEntitySetForColumnsMappedToEntityKeys(cells, ParentColumns);

            if (entitySet == null || endSet.Equals(entitySet) == false)
            {
                if (errorList == null) //lazily initialize only if there is an error
                {
                    errorList = new List <ErrorLog.Record>();
                }

                // childColumns are mapped to parentEnd but ParentColumns are not mapped to the end
                // corresponding to the parentEnd -- this is an error
                string message = System.Data.Entity.Strings.ViewGen_Foreign_Key_ParentTable_NotMappedToEnd(
                    ToUserString(), ChildTable.Name,
                    cell.CQuery.Extent.Name, parentEnd.Name, ParentTable.Name, endSet.Name);
                ErrorLog.Record record = new ErrorLog.Record(true, ViewGenErrorCode.ForeignKeyParentTableNotMappedToEnd, message, cell, String.Empty);
                errorList.Add(record);
                return(false);
            }
            return(true);
        }
Ejemplo n.º 19
0
 /// <summary>
 ///     Given an AssociationEndMember of this Association, this method will return the other end participating
 ///     in the association
 /// </summary>
 /// <param name="association">The Association.</param>
 /// <param name="end">An AssociationEndMember.</param>
 /// <returns>The other end.</returns>
 public static AssociationEndMember GetOtherEnd(this AssociationType association, AssociationEndMember end)
 {
     if (end != null)
     {
         return(end == association.GetEnd1() ? association.GetEnd2() : association.GetEnd1());
     }
     return(null);
 }
Ejemplo n.º 20
0
        internal static bool DoesEndKeySubsumeAssociationSetKey(AssociationSet assocSet, AssociationEndMember thisEnd, HashSet <Pair <EdmMember, EntityType> > associationkeys)
        {
            AssociationType assocType          = assocSet.ElementType;
            EntityType      thisEndsEntityType = (EntityType)((RefType)thisEnd.TypeUsage.EdmType).ElementType;

            HashSet <Pair <EdmMember, EntityType> > thisEndKeys = new HashSet <Pair <EdmMember, EntityType> >(
                thisEndsEntityType.KeyMembers.Select(edmMember => new Pair <EdmMember, EntityType>(edmMember, thisEndsEntityType)));

            foreach (ReferentialConstraint constraint in assocType.ReferentialConstraints)
            {
                IEnumerable <EdmMember> otherEndProperties;
                EntityType otherEndType;

                if (thisEnd.Equals((AssociationEndMember)constraint.ToRole))
                {
                    otherEndProperties = Helpers.AsSuperTypeList <EdmProperty, EdmMember>(constraint.FromProperties);
                    otherEndType       = (EntityType)((RefType)((AssociationEndMember)constraint.FromRole).TypeUsage.EdmType).ElementType;
                }
                else if (thisEnd.Equals((AssociationEndMember)constraint.FromRole))
                {
                    otherEndProperties = Helpers.AsSuperTypeList <EdmProperty, EdmMember>(constraint.ToProperties);
                    otherEndType       = (EntityType)((RefType)((AssociationEndMember)constraint.ToRole).TypeUsage.EdmType).ElementType;
                }
                else
                {
                    //this end not part of the referential constraint
                    continue;
                }

                //Essentially ref constraints is an equality condition, so remove redundant members from entity set key
                foreach (EdmMember member in otherEndProperties)
                {
                    associationkeys.Remove(new Pair <EdmMember, EntityType>(member, otherEndType));
                }
            }

            //Now that all redundant members have been removed, is thisEnd the key of the entity set?
            return(associationkeys.IsSubsetOf(thisEndKeys));
        }
        private static Func <RelationshipManager, RelatedEnd, RelatedEnd> CreateGetRelatedEndMethod(AssociationEndMember sourceMember, AssociationEndMember targetMember)
        {
            Debug.Assert(sourceMember.DeclaringType == targetMember.DeclaringType, "Source and Target members must be in the same DeclaringType");

            EntityType sourceEntityType = MetadataHelper.GetEntityTypeForEnd(sourceMember);
            EntityType targetEntityType = MetadataHelper.GetEntityTypeForEnd(targetMember);
            NavigationPropertyAccessor sourceAccessor = MetadataHelper.GetNavigationPropertyAccessor(targetEntityType, targetMember, sourceMember);
            NavigationPropertyAccessor targetAccessor = MetadataHelper.GetNavigationPropertyAccessor(sourceEntityType, sourceMember, targetMember);

            MethodInfo genericCreateRelatedEndMethod = typeof(LightweightCodeGenerator).GetMethod("CreateGetRelatedEndMethod", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(AssociationEndMember), typeof(AssociationEndMember), typeof(NavigationPropertyAccessor), typeof(NavigationPropertyAccessor) }, null);

            Debug.Assert(genericCreateRelatedEndMethod != null, "Could not find method LightweightCodeGenerator.CreateGetRelatedEndMethod");

            MethodInfo createRelatedEndMethod = genericCreateRelatedEndMethod.MakeGenericMethod(sourceEntityType.ClrType, targetEntityType.ClrType);
            object     getRelatedEndDelegate  = createRelatedEndMethod.Invoke(null, new object[] { sourceMember, targetMember, sourceAccessor, targetAccessor });

            return((Func <RelationshipManager, RelatedEnd, RelatedEnd>)getRelatedEndDelegate);
        }
Ejemplo n.º 22
0
 internal static NavigationPropertyAccessor GetNavigationPropertyAccessor(EntityType sourceEntityType, AssociationEndMember sourceMember, AssociationEndMember targetMember)
 {
     Debug.Assert(sourceEntityType.DataSpace == DataSpace.OSpace && sourceEntityType.ClrType != null, "sourceEntityType must contain an ospace type");
     return(GetNavigationPropertyAccessor(sourceEntityType, sourceMember.DeclaringType.FullName, sourceMember.Name, targetMember.Name));
 }
        /// <summary>
        /// Gets the related end instance for the source AssociationEndMember by creating a DynamicMethod to
        /// call GetRelatedCollection or GetRelatedReference
        /// </summary>
        internal static RelatedEnd GetRelatedEnd(RelationshipManager sourceRelationshipManager, AssociationEndMember sourceMember, AssociationEndMember targetMember, RelatedEnd existingRelatedEnd)
        {
            Func <RelationshipManager, RelatedEnd, RelatedEnd> getRelatedEnd = sourceMember.GetRelatedEnd;

            if (null == getRelatedEnd)
            {
                getRelatedEnd = CreateGetRelatedEndMethod(sourceMember, targetMember);
                sourceMember.GetRelatedEnd = getRelatedEnd;
            }
            Debug.Assert(null != getRelatedEnd, "null getRelatedEnd");

            return(getRelatedEnd(sourceRelationshipManager, existingRelatedEnd));
        }
Ejemplo n.º 24
0
        private void logForeignKeyChange(ObjectStateEntry entry, AssociationEndMember localEnd, AssociationEndMember foreignEnd)
        {
            // These "keys" represent in-memory unique references
            // to the objects at the ends of these associations.
            // In the case of new objects, these won't contain the primary key that has just
            // been generated, but we can still use it below to get to the real object in-memory
            // and pull the id out of that.
            var key = getEndEntityKey(entry, localEnd);

            // Get the object identified by the local key
            object entity = context.GetObjectByKey(key);

            if (!filter.ShouldLog(entity.GetType()))
            {
                return;
            }

            // The property on the "local" object that navigates to the "foreign" object
            var property = getProperty(entry, localEnd, foreignEnd, key);

            // We can control which directions of relationships we are interested in logging
            // by which navigation properties we keep in the model
            if (property == null || !filter.ShouldLog(property))
            {
                return;
            }

            // Generate the change
            Func <object> value = getForeignValue(entry, entity, foreignEnd, property.Name);

            recorder.Record(entity, context.GetReferenceForObject(entity), property.Name, value, entry.State, null /* TODO: Fabricio retirar */);
        }
        public void Can_generate_function_mappings_for_many_to_many_association_set_mapping()
        {
            var databaseMapping
                = new DbDatabaseMapping()
                  .Initialize(new EdmModel(DataSpace.CSpace), new EdmModel(DataSpace.SSpace));

            var entityType1 = databaseMapping.Model.AddEntityType("E1");

            entityType1.Annotations.SetClrType(typeof(string));
            databaseMapping.Model.AddEntitySet("E1Set", entityType1);

            var entityType2 = databaseMapping.Model.AddEntityType("E2");

            entityType2.Annotations.SetClrType(typeof(string));
            databaseMapping.Model.AddEntitySet("E2Set", entityType2);

            var entityTypeConfiguration = new EntityTypeConfiguration(typeof(object));

            entityTypeConfiguration.MapToStoredProcedures();
            entityType1.SetConfiguration(entityTypeConfiguration);
            entityType2.SetConfiguration(entityTypeConfiguration);

            var associationSet
                = databaseMapping.Model.AddAssociationSet(
                      "M2MSet",
                      databaseMapping.Model.AddAssociationType(
                          "M2M",
                          entityType1,
                          RelationshipMultiplicity.Many,
                          entityType2,
                          RelationshipMultiplicity.Many));

            var entitySet = new EntitySet("ES", "S", null, null, new EntityType("E", "N", DataSpace.CSpace));

            var associationEndMember1 = new AssociationEndMember("Source", new EntityType("E", "N", DataSpace.CSpace));

            associationSet.AddAssociationSetEnd(new AssociationSetEnd(entitySet, associationSet, associationEndMember1));

            var associationEndMember2 = new AssociationEndMember("Target", new EntityType("E", "N", DataSpace.CSpace));

            associationSet.AddAssociationSetEnd(new AssociationSetEnd(entitySet, associationSet, associationEndMember2));

            var associationSetMapping
                = new StorageAssociationSetMapping(
                      associationSet,
                      entitySet)
                {
                SourceEndMapping
                    = new StorageEndPropertyMapping()
                    {
                    EndMember = associationEndMember1
                    },
                TargetEndMapping
                    = new StorageEndPropertyMapping()
                    {
                    EndMember = associationEndMember2
                    }
                };

            associationSetMapping.SourceEndMapping
            .AddProperty(new StorageScalarPropertyMapping(new EdmProperty("PK"), new EdmProperty("FooId")));

            associationSetMapping.TargetEndMapping
            .AddProperty(new StorageScalarPropertyMapping(new EdmProperty("PK"), new EdmProperty("BarId")));

            var functionMappingGenerator
                = new ModificationFunctionMappingGenerator(ProviderRegistry.Sql2008_ProviderManifest);

            functionMappingGenerator.Generate(associationSetMapping, databaseMapping);

            var modificationFunctionMapping
                = associationSetMapping.ModificationFunctionMapping;

            Assert.NotNull(modificationFunctionMapping);

            var functionMapping = modificationFunctionMapping.InsertFunctionMapping;

            Assert.NotNull(functionMapping);
            Assert.Equal(2, functionMapping.ParameterBindings.Count);
            Assert.Null(functionMapping.ResultBindings);

            var function = functionMapping.Function;

            Assert.NotNull(function);
            Assert.Equal("E1E2_Insert", function.Name);
            Assert.Equal(2, function.Parameters.Count);

            functionMapping = modificationFunctionMapping.DeleteFunctionMapping;

            Assert.NotNull(functionMapping);
            Assert.Equal(2, functionMapping.ParameterBindings.Count);
            Assert.Null(functionMapping.ResultBindings);

            function = modificationFunctionMapping.DeleteFunctionMapping.Function;

            Assert.NotNull(function);
            Assert.Equal("E1E2_Delete", function.Name);
            Assert.Equal(2, function.Parameters.Count);
        }
Ejemplo n.º 26
0
        // <summary>
        // Call to ensure a target entities key is added into the state manager
        // properly
        // </summary>
        public IEntityWrapper HandleRelationshipSpan(
            IEntityWrapper wrappedEntity, EntityKey targetKey, AssociationEndMember targetMember)
        {
            if (null == wrappedEntity.Entity)
            {
                return(wrappedEntity);
            }
            DebugCheck.NotNull(targetMember);
            Debug.Assert(
                targetMember.RelationshipMultiplicity == RelationshipMultiplicity.One ||
                targetMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne);

            var sourceKey    = wrappedEntity.EntityKey;
            var sourceMember = MetadataHelper.GetOtherAssociationEnd(targetMember);

            CheckClearedEntryOnSpan(targetKey, wrappedEntity, sourceKey, targetMember);

            if (null != (object)targetKey)
            {
                EntitySet targetEntitySet;

                var associationSet = Context.MetadataWorkspace.MetadataOptimization.FindCSpaceAssociationSet(
                    (AssociationType)targetMember.DeclaringType, targetMember.Name,
                    targetKey.EntitySetName, targetKey.EntityContainerName, out targetEntitySet);
                Debug.Assert(associationSet != null, "associationSet should not be null");

                var         manager = Context.ObjectStateManager;
                EntityState newEntryState;
                // If there is an existing relationship entry, update it based on its current state and the MergeOption, otherwise add a new one
                if (
                    !ObjectStateManager.TryUpdateExistingRelationships(
                        Context, MergeOption, associationSet, sourceMember, sourceKey, wrappedEntity, targetMember, targetKey,
                        /*setIsLoaded*/ true, out newEntryState))
                {
                    // Try to find a state entry for the target key
                    var targetEntry = manager.GetOrAddKeyEntry(targetKey, targetEntitySet);

                    // For 1-1 relationships we have to take care of the relationships of targetEntity
                    var needNewRelationship = true;
                    switch (sourceMember.RelationshipMultiplicity)
                    {
                    case RelationshipMultiplicity.ZeroOrOne:
                    case RelationshipMultiplicity.One:
                        // devnote: targetEntry can be a key entry (targetEntry.Entity == null),
                        // but it that case this parameter won't be used in TryUpdateExistingRelationships
                        needNewRelationship = !ObjectStateManager.TryUpdateExistingRelationships(
                            Context,
                            MergeOption,
                            associationSet,
                            targetMember,
                            targetKey,
                            targetEntry.WrappedEntity,
                            sourceMember,
                            sourceKey,
                            setIsLoaded: true,
                            newEntryState: out newEntryState);

                        // It is possible that as part of removing existing relationships, the key entry was deleted
                        // If that is the case, recreate the key entry
                        if (targetEntry.State
                            == EntityState.Detached)
                        {
                            targetEntry = manager.AddKeyEntry(targetKey, targetEntitySet);
                        }
                        break;

                    case RelationshipMultiplicity.Many:
                        // we always need a new relationship with Many-To-Many, if there was no exact match between these two entities, so do nothing
                        break;

                    default:
                        Debug.Assert(false, "Unexpected sourceMember.RelationshipMultiplicity");
                        break;
                    }

                    if (needNewRelationship)
                    {
                        // If the target entry is a key entry, then we need to add a relation
                        //   between the source and target entries
                        // If we are in a state where we just need to add a new Deleted relation, we
                        //   only need to do that and not touch the related ends
                        // If the target entry is a full entity entry, then we need to add
                        //   the target entity to the source collection or reference
                        if (targetEntry.IsKeyEntry ||
                            newEntryState == EntityState.Deleted)
                        {
                            // Add a relationship between the source entity and the target key entry
                            var wrapper = new RelationshipWrapper(
                                associationSet, sourceMember.Name, sourceKey, targetMember.Name, targetKey);
                            manager.AddNewRelation(wrapper, newEntryState);
                        }
                        else
                        {
                            Debug.Assert(!targetEntry.IsRelationship, "how IsRelationship?");
                            if (targetEntry.State
                                != EntityState.Deleted)
                            {
                                // The entry contains an entity, do collection or reference fixup
                                // This will also try to create a new relationship entry or will revert the delete on an existing deleted relationship
                                ObjectStateManager.AddEntityToCollectionOrReference(
                                    MergeOption, wrappedEntity, sourceMember,
                                    targetEntry.WrappedEntity,
                                    targetMember,
                                    setIsLoaded: true,
                                    relationshipAlreadyExists: false,
                                    inKeyEntryPromotion: false);
                            }
                            else
                            {
                                // if the target entry is deleted, then the materializer needs to create a deleted relationship
                                // between the entity and the target entry so that if the entity is deleted, the update
                                // pipeline can find the relationship (even though it is deleted)
                                var wrapper = new RelationshipWrapper(
                                    associationSet, sourceMember.Name, sourceKey, targetMember.Name, targetKey);
                                manager.AddNewRelation(wrapper, EntityState.Deleted);
                            }
                        }
                    }
                }
            }
            else
            {
                RelatedEnd relatedEnd;
                if (TryGetRelatedEnd(
                        wrappedEntity, (AssociationType)targetMember.DeclaringType, sourceMember.Name, targetMember.Name, out relatedEnd))
                {
                    SetIsLoadedForSpan(relatedEnd, false);
                }
            }

            // else there is nothing else for us to do, the relationship has been handled already
            return(wrappedEntity);
        }
Ejemplo n.º 27
0
        internal void CreateAssociationConstraints(EntitySetBase extent, MemberDomainMap domainMap, EdmItemCollection edmItemCollection)
        {
            AssociationSet assocSet = extent as AssociationSet;

            if (assocSet != null)
            {
                BoolExpression assocSetExpr = BoolExpression.CreateLiteral(new RoleBoolean(assocSet), domainMap);

                //Set of Keys for this Association Set
                //need to key on EdmMember and EdmType because A, B subtype of C, can have the same id (EdmMember) that is defined in C.
                HashSet <Pair <EdmMember, EntityType> > associationkeys = new HashSet <Pair <EdmMember, EntityType> >();


                //foreach end, add each Key
                foreach (var endMember in assocSet.ElementType.AssociationEndMembers)
                {
                    EntityType type = (EntityType)((RefType)endMember.TypeUsage.EdmType).ElementType;
                    type.KeyMembers.All(member => associationkeys.Add(new Pair <EdmMember, EntityType>(member, type)) || true /* prevent early termination */);
                }

                foreach (AssociationSetEnd end in assocSet.AssociationSetEnds)
                {
                    // construct type condition
                    HashSet <EdmType> derivedTypes = new HashSet <EdmType>();
                    derivedTypes.UnionWith(MetadataHelper.GetTypeAndSubtypesOf(end.CorrespondingAssociationEndMember.TypeUsage.EdmType, edmItemCollection, false));

                    BoolExpression typeCondition = CreateIsOfTypeCondition(new MemberPath(end.EntitySet),
                                                                           derivedTypes, domainMap);

                    BoolExpression inRoleExpression = BoolExpression.CreateLiteral(new RoleBoolean(end), domainMap);
                    BoolExpression inSetExpression  = BoolExpression.CreateAnd(
                        BoolExpression.CreateLiteral(new RoleBoolean(end.EntitySet), domainMap),
                        typeCondition);

                    // InRole -> (InSet AND type(Set)=T)
                    AddImplication(inRoleExpression.Tree, inSetExpression.Tree);

                    if (MetadataHelper.IsEveryOtherEndAtLeastOne(assocSet, end.CorrespondingAssociationEndMember))
                    {
                        AddImplication(inSetExpression.Tree, inRoleExpression.Tree);
                    }

                    // Add equivalence between association set an End/Role if necessary.
                    //   Equivalence is added when a given association end's keys subsumes keys for
                    //   all the other association end.

                    // For example: We have Entity Sets A[id1], B[id2, id3] and an association A_B between them.
                    // Ref Constraint A.id1 = B.id2
                    // In this case, the Association Set has Key <id1, id2, id3>
                    // id1 alone can not identify a unique tuple in the Association Set, but <id2, id3> can.
                    // Therefore we add a constraint: InSet(B) <=> InEnd(A_B.B)

                    if (MetadataHelper.DoesEndKeySubsumeAssociationSetKey(assocSet,
                                                                          end.CorrespondingAssociationEndMember,
                                                                          associationkeys))
                    {
                        AddEquivalence(inRoleExpression.Tree, assocSetExpr.Tree);
                    }
                }

                // add rules for referential constraints (borrowed from LeftCellWrapper.cs)
                AssociationType assocType = assocSet.ElementType;

                foreach (ReferentialConstraint constraint in assocType.ReferentialConstraints)
                {
                    AssociationEndMember toEndMember = (AssociationEndMember)constraint.ToRole;
                    EntitySet            toEntitySet = MetadataHelper.GetEntitySetAtEnd(assocSet, toEndMember);
                    // Check if the keys of the entitySet's are equal to what is specified in the constraint
                    // How annoying that KeyMembers returns EdmMember and not EdmProperty
                    IEnumerable <EdmMember> toProperties = Helpers.AsSuperTypeList <EdmProperty, EdmMember>(constraint.ToProperties);
                    if (Helpers.IsSetEqual(toProperties, toEntitySet.ElementType.KeyMembers, EqualityComparer <EdmMember> .Default))
                    {
                        // Now check that the FromEnd is 1..1 (only then will all the Addresses be present in the assoc set)
                        if (constraint.FromRole.RelationshipMultiplicity.Equals(RelationshipMultiplicity.One))
                        {
                            // Make sure that the ToEnd is not 0..* because then the schema is broken
                            Debug.Assert(constraint.ToRole.RelationshipMultiplicity.Equals(RelationshipMultiplicity.Many) == false);
                            // Equate the ends
                            BoolExpression inRoleExpression1 = BoolExpression.CreateLiteral(new RoleBoolean(assocSet.AssociationSetEnds[0]), domainMap);
                            BoolExpression inRoleExpression2 = BoolExpression.CreateLiteral(new RoleBoolean(assocSet.AssociationSetEnds[1]), domainMap);
                            AddEquivalence(inRoleExpression1.Tree, inRoleExpression2.Tree);
                        }
                    }
                }
            }
        }
Ejemplo n.º 28
0
        private bool TryGetRelatedEnd(
            IEntityWrapper wrappedEntity, AssociationType associationType, string sourceEndName, string targetEndName,
            out RelatedEnd relatedEnd)
        {
            Debug.Assert(associationType.DataSpace == DataSpace.CSpace);

            // Get the OSpace AssociationType
            var oSpaceAssociation = Workspace.MetadataOptimization.GetOSpaceAssociationType(associationType,
                                                                                            () => Workspace.GetItemCollection(DataSpace.OSpace).GetItem <AssociationType>(associationType.FullName));

            AssociationEndMember sourceEnd = null;
            AssociationEndMember targetEnd = null;

            foreach (var end in oSpaceAssociation.AssociationEndMembers)
            {
                if (end.Name == sourceEndName)
                {
                    sourceEnd = end;
                }
                else if (end.Name == targetEndName)
                {
                    targetEnd = end;
                }
            }

            if (sourceEnd != null &&
                targetEnd != null)
            {
                var createRelatedEnd = false;
                if (wrappedEntity.EntityKey == null)
                {
                    // Free-floating entity--key is null, so don't have EntitySet for validation, so always create RelatedEnd
                    createRelatedEnd = true;
                }
                else
                {
                    // It is possible, because of MEST, that we're trying to load a relationship that is valid for this EntityType
                    // in metadata, but is not valid in this case because the specific entity is part of an EntitySet that is not
                    // mapped in any AssociationSet for this association type.
                    // The metadata structure makes checking for this somewhat time consuming because of the loop required.
                    // Because the whole reason for this method is perf, we try to reduce the
                    // impact of this check by caching positive hits in a HashSet so we don't have to do this for
                    // every entity in a query.  (We could also cache misses, but since these only happen in MEST, which
                    // is not common, we decided not to slow down the normal non-MEST case anymore by doing this.)
                    EntitySet entitySet;
                    var       associationSet = Workspace.MetadataOptimization.FindCSpaceAssociationSet(associationType, sourceEndName,
                                                                                                       wrappedEntity.EntityKey.EntitySetName, wrappedEntity.EntityKey.EntityContainerName, out entitySet);
                    if (associationSet != null)
                    {
                        createRelatedEnd = true;
                    }
                }
                if (createRelatedEnd)
                {
                    relatedEnd = DelegateFactory.GetRelatedEnd(wrappedEntity.RelationshipManager, sourceEnd, targetEnd, null);
                    return(true);
                }
            }

            relatedEnd = null;
            return(false);
        }
        public void WriteAssociationSetMapping_should_write_modification_function_mapping()
        {
            var fixture = new Fixture();

            var entityType = new EntityType("E", "N", DataSpace.CSpace);
            var entitySet  = new EntitySet("ES", "S", null, null, entityType);

            new EntityContainer("EC", DataSpace.SSpace).AddEntitySetBase(entitySet);
            var associationSet = new AssociationSet("AS", new AssociationType("A", XmlConstants.ModelNamespace_3, false, DataSpace.CSpace));

            var associationEndMember1 = new AssociationEndMember("Source", new EntityType("E", "N", DataSpace.CSpace));

            associationSet.AddAssociationSetEnd(new AssociationSetEnd(entitySet, associationSet, associationEndMember1));

            var associationEndMember2 = new AssociationEndMember("Target", new EntityType("E", "N", DataSpace.CSpace));

            associationSet.AddAssociationSetEnd(new AssociationSetEnd(entitySet, associationSet, associationEndMember2));

            var storageModificationFunctionMapping
                = new StorageModificationFunctionMapping(
                      associationSet,
                      associationSet.ElementType,
                      new EdmFunction("F", "N", DataSpace.SSpace, new EdmFunctionPayload()),
                      new[]
            {
                new StorageModificationFunctionParameterBinding(
                    new FunctionParameter(
                        "P",
                        TypeUsage.Create(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)),
                        ParameterMode.In),
                    new StorageModificationFunctionMemberPath(
                        new EdmMember[]
                {
                    new EdmProperty("K"),
                    associationEndMember1
                },
                        associationSet),
                    true),
                new StorageModificationFunctionParameterBinding(
                    new FunctionParameter(
                        "P",
                        TypeUsage.Create(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)),
                        ParameterMode.In),
                    new StorageModificationFunctionMemberPath(
                        new EdmMember[]
                {
                    new EdmProperty("K"),
                    associationEndMember2
                },
                        associationSet),
                    false)
            },
                      null,
                      null);

            var associationSetMapping
                = new StorageAssociationSetMapping(
                      associationSet,
                      entitySet)
                {
                SourceEndMapping
                    = new StorageEndPropertyMapping
                    {
                    EndMember = associationEndMember1
                    },
                TargetEndMapping
                    = new StorageEndPropertyMapping
                    {
                    EndMember = associationEndMember2
                    },
                ModificationFunctionMapping = new StorageAssociationSetModificationFunctionMapping(
                    associationSet,
                    storageModificationFunctionMapping,
                    storageModificationFunctionMapping)
                };

            fixture.Writer.WriteAssociationSetMappingElement(associationSetMapping);

            Assert.Equal(
                @"<AssociationSetMapping Name=""AS"" TypeName="".A"" StoreEntitySet=""E"">
  <EndProperty Name=""Source"" />
  <EndProperty Name=""Target"" />
  <ModificationFunctionMapping>
    <InsertFunction FunctionName=""N.F"">
      <EndProperty Name=""Source"">
        <ScalarProperty Name=""K"" ParameterName=""P"" Version=""Current"" />
      </EndProperty>
      <EndProperty Name=""Target"">
        <ScalarProperty Name=""K"" ParameterName=""P"" Version=""Original"" />
      </EndProperty>
    </InsertFunction>
    <DeleteFunction FunctionName=""N.F"">
      <EndProperty Name=""Source"">
        <ScalarProperty Name=""K"" ParameterName=""P"" Version=""Current"" />
      </EndProperty>
      <EndProperty Name=""Target"">
        <ScalarProperty Name=""K"" ParameterName=""P"" Version=""Original"" />
      </EndProperty>
    </DeleteFunction>
  </ModificationFunctionMapping>
</AssociationSetMapping>",
                fixture.ToString());
        }
Ejemplo n.º 30
0
        internal void Delete(bool doFixup)
        {
            this.ValidateState();
            if (doFixup)
            {
                if (this.State == EntityState.Deleted)
                {
                    return;
                }
                EntityEntry    entityEntry1   = this._cache.GetEntityEntry((EntityKey)this.GetCurrentRelationValue(0));
                IEntityWrapper wrappedEntity1 = entityEntry1.WrappedEntity;
                EntityEntry    entityEntry2   = this._cache.GetEntityEntry((EntityKey)this.GetCurrentRelationValue(1));
                IEntityWrapper wrappedEntity2 = entityEntry2.WrappedEntity;
                if (wrappedEntity1.Entity != null && wrappedEntity2.Entity != null)
                {
                    string name     = this._relationshipWrapper.AssociationEndMembers[1].Name;
                    string fullName = ((AssociationSet)this._entitySet).ElementType.FullName;
                    wrappedEntity1.RelationshipManager.RemoveEntity(name, fullName, wrappedEntity2);
                }
                else
                {
                    EntityKey           entityKey;
                    RelationshipManager relationshipManager;
                    if (wrappedEntity1.Entity == null)
                    {
                        entityKey           = entityEntry1.EntityKey;
                        relationshipManager = wrappedEntity2.RelationshipManager;
                    }
                    else
                    {
                        entityKey           = entityEntry2.EntityKey;
                        relationshipManager = wrappedEntity1.RelationshipManager;
                    }
                    AssociationEndMember associationEndMember = this.RelationshipWrapper.GetAssociationEndMember(entityKey);
                    ((EntityReference)relationshipManager.GetRelatedEndInternal(associationEndMember.DeclaringType.FullName, associationEndMember.Name)).DetachedEntityKey = (EntityKey)null;
                    if (this.State == EntityState.Added)
                    {
                        this.DeleteUnnecessaryKeyEntries();
                        this.DetachRelationshipEntry();
                    }
                    else
                    {
                        this._cache.ChangeState(this, this.State, EntityState.Deleted);
                        this.State = EntityState.Deleted;
                    }
                }
            }
            else
            {
                switch (this.State)
                {
                case EntityState.Unchanged:
                    this._cache.ChangeState(this, EntityState.Unchanged, EntityState.Deleted);
                    this.State = EntityState.Deleted;
                    break;

                case EntityState.Added:
                    this.DeleteUnnecessaryKeyEntries();
                    this.DetachRelationshipEntry();
                    break;
                }
            }
        }
Ejemplo n.º 31
0
 // effects: Returns the entity set at the end corresponding to endMember
 internal static EntitySet GetEntitySetAtEnd(
     AssociationSet associationSet,
     AssociationEndMember endMember)
 {
     return(associationSet.AssociationSetEnds[endMember.Name].EntitySet);
 }
 /// <summary>
 /// Populate the ResourceAssociationTypeEnd from the AssociationEndMember instance.
 /// </summary>
 /// <param name="end">Instance of AssociationEndMember.</param>
 /// <param name="resourceType">ResourceType instance which the end refers to.</param>
 /// <param name="resourceProperty">ResourceProperty instance.</param>
 /// <returns>An instance of ResourceAssociationTypeEnd.</returns>
 private static ResourceAssociationTypeEnd PopulateResourceAssociationTypeEnd(AssociationEndMember end, ResourceType resourceType, ResourceProperty resourceProperty)
 {
     ResourceAssociationTypeEnd resourceAssociationTypeEnd = new ResourceAssociationTypeEnd(end.Name, resourceType, resourceProperty, ObjectContextServiceProvider.GetMultiplicity(end.RelationshipMultiplicity), (EdmOnDeleteAction)end.DeleteBehavior);
     ObjectContextServiceProvider.PopulateAnnotations(end.MetadataProperties, resourceAssociationTypeEnd.AddCustomAnnotation);
     return resourceAssociationTypeEnd;
 }