/// <summary> /// Returns the association information for the specified navigation property. /// </summary> /// <param name="navigationProperty">The navigation property to return association information for</param> /// <returns>The association info</returns> internal AssociationInfo GetAssociationInfo(NavigationProperty navigationProperty) { return _associationMap.GetOrAdd(navigationProperty.RelationshipType.FullName, associationName => { AssociationType associationType = (AssociationType)navigationProperty.RelationshipType; if (!associationType.ReferentialConstraints.Any()) { // We only support EF models where FK info is part of the model. throw Error.NotSupported(Resource.LinqToEntitiesProvider_UnableToRetrieveAssociationInfo, associationName); } string toRoleName = associationType.ReferentialConstraints[0].ToRole.Name; AssociationInfo associationInfo = new AssociationInfo() { FKRole = toRoleName, Name = GetAssociationName(navigationProperty, toRoleName), ThisKey = associationType.ReferentialConstraints[0].ToProperties.Select(p => p.Name).ToArray(), OtherKey = associationType.ReferentialConstraints[0].FromProperties.Select(p => p.Name).ToArray(), IsRequired = associationType.RelationshipEndMembers[0].RelationshipMultiplicity == RelationshipMultiplicity.One }; return associationInfo; }); }
private void CreateAndAddNavigationProperty(StructuralType cspaceType, StructuralType ospaceType, NavigationProperty cspaceProperty, PropertyInfo clrProperty) { EdmType ospaceRelationship; if (SessionData.CspaceToOspace.TryGetValue(cspaceProperty.RelationshipType, out ospaceRelationship)) { Debug.Assert(ospaceRelationship is StructuralType, "Structural type expected."); bool foundTarget = false; EdmType targetType = null; if (Helper.IsCollectionType(cspaceProperty.TypeUsage.EdmType)) { EdmType findType; foundTarget = SessionData.CspaceToOspace.TryGetValue((StructuralType)((CollectionType)cspaceProperty.TypeUsage.EdmType).TypeUsage.EdmType, out findType); if (foundTarget) { Debug.Assert(findType is StructuralType, "Structural type expected."); targetType = findType.GetCollectionType(); } } else { EdmType findType; foundTarget = SessionData.CspaceToOspace.TryGetValue((StructuralType)cspaceProperty.TypeUsage.EdmType, out findType); if (foundTarget) { Debug.Assert(findType is StructuralType, "Structural type expected."); targetType = findType; } } Debug.Assert(foundTarget, "Since the relationship will only be created if it can find the types for both ends, we will never fail to find one of the ends"); NavigationProperty navigationProperty = new NavigationProperty(cspaceProperty.Name, TypeUsage.Create(targetType), clrProperty); navigationProperty.RelationshipType = (RelationshipType)ospaceRelationship; // we can use First because o-space relationships are created directly from // c-space relationship navigationProperty.ToEndMember = (RelationshipEndMember)((RelationshipType)ospaceRelationship).Members.First(e => e.Name == cspaceProperty.ToEndMember.Name); navigationProperty.FromEndMember = (RelationshipEndMember)((RelationshipType)ospaceRelationship).Members.First(e => e.Name == cspaceProperty.FromEndMember.Name); ospaceType.AddMember(navigationProperty); } else { EntityTypeBase missingType = cspaceProperty.RelationshipType.RelationshipEndMembers.Select(e => ((RefType)e.TypeUsage.EdmType).ElementType).First(e => e != cspaceType); string message = SessionData.LoadMessageLogger.CreateErrorMessageWithTypeSpecificLoadLogs( Strings.Validator_OSpace_Convention_RelationshipNotLoaded(cspaceProperty.RelationshipType.FullName, missingType.FullName), missingType); SessionData.EdmItemErrors.Add(new EdmItemError(message, ospaceType)); } }
/// <summary> /// Given a property on the principal end of a referential constraint, returns the corresponding property on the dependent end. /// Requires: The association has a referential constraint, and the specified principalProperty is one of the properties on the principal end. /// </summary> public EdmProperty GetCorrespondingDependentProperty(NavigationProperty navProperty, EdmProperty principalProperty) { if (navProperty == null) { throw new ArgumentNullException("navProperty"); } if (principalProperty == null) { throw new ArgumentNullException("principalProperty"); } ReadOnlyMetadataCollection<EdmProperty> fromProperties = GetPrincipalProperties(navProperty); ReadOnlyMetadataCollection<EdmProperty> toProperties = GetDependentProperties(navProperty); return toProperties[fromProperties.IndexOf(principalProperty)]; }
public EFAssociationProvider(EFColumnProvider column, NavigationProperty navigationProperty) { FromColumn = column; var entityMemberParentEntity = (EFTableProvider)column.Table; var parentEntityModel = (EFDataModelProvider)entityMemberParentEntity.DataModel; EFColumnProvider columnProvider; EntityType otherEntityType = navigationProperty.ToEndMember.GetEntityType(); // If we can get to the entityType of the ToMember side of the relaionship then build a relationship key and try to lookup the column provider. if (otherEntityType != null) { long key = BuildRelationshipKey(otherEntityType, navigationProperty.ToEndMember); if (parentEntityModel.RelationshipEndLookup.TryGetValue(key, out columnProvider)) { ToColumn = columnProvider; } else { // Otherwise just lookup the entityType in the table lookup ToTable = parentEntityModel.TableEndLookup[otherEntityType]; } } else { EntityType value = (EntityType)navigationProperty.ToEndMember.TypeUsage.EdmType.MetadataProperties.Single(prop => prop.Name == "ElementType").Value; ToTable = parentEntityModel.TableEndLookup[value]; } if (navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) { if (navigationProperty.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) { Direction = AssociationDirection.ManyToMany; } else { Direction = AssociationDirection.OneToMany; } } else { if (navigationProperty.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) { Direction = AssociationDirection.ManyToOne; } else { Direction = AssociationDirection.OneToOne; } } // If it's a foreign key reference (as opposed to a entity set), figure out the foreign keys if (IsForeignKeyReference) { var foreignKeyNames = new List<string>(); var primaryKeyNames = FromColumn.Table.Columns.Where(c => c.IsPrimaryKey).Select(c => c.Name); // Add the foreign keys for this association. foreignKeyNames.AddRange(GetDependentPropertyNames(navigationProperty)); if (IsZeroOrOne(navigationProperty)) { // Assume this is true for 1 to 0..1 relationships on both sides IsPrimaryKeyInThisTable = true; } else { // If any of the foreign keys are also PKs, set the flag IsPrimaryKeyInThisTable = foreignKeyNames.Any(fkName => primaryKeyNames.Contains(fkName, StringComparer.OrdinalIgnoreCase)); } if (!foreignKeyNames.Any()) { // If we couldn't find any dependent properties, we're dealing with a model that doesn't // have FKs, and requires the use of flattened FK names (e.g. Category.CategoryId) foreach (ColumnProvider toEntityColumn in ToTable.Columns.Where(c => c.IsPrimaryKey)) { foreignKeyNames.Add(FromColumn.Name + "." + toEntityColumn.Name); } } ForeignKeyNames = foreignKeyNames.AsReadOnly(); } }
/// <summary> /// Validate an NavigationProperty object /// </summary> /// <param name="item">The NavigationProperty object to validate</param> /// <param name="errors">An error collection for adding validation errors</param> /// <param name="validatedItems">A dictionary keeping track of items that have been validated</param> private void ValidateNavigationProperty(NavigationProperty item, List <EdmItemError> errors, HashSet <MetadataItem> validatedItems) { // Continue to process the property to see if there are other errors. This allows the user to fix as much as possible at the same time. ValidateEdmMember(item, errors, validatedItems); }
/// <summary> /// True if the source end of the specified navigation property is the principal in an identifying relationship. /// or if the source end has cascade delete defined. /// </summary> public bool IsCascadeDeletePrincipal(NavigationProperty navProperty) { if (navProperty == null) { throw new ArgumentNullException("navProperty"); } return IsCascadeDeletePrincipal((AssociationEndMember)navProperty.FromEndMember); }
protected virtual void Visit(NavigationProperty navigationProperty) { Visit(navigationProperty.FromEndMember); Visit(navigationProperty.RelationshipType); Visit(navigationProperty.ToEndMember); Visit(navigationProperty.TypeUsage); }
private Node RewriteNavigationProperty( NavigationProperty navProperty, Node sourceEntityNode, TypeUsage resultType) { var relProperty = new RelProperty(navProperty.RelationshipType, navProperty.FromEndMember, navProperty.ToEndMember); PlanCompiler.Assert( m_command.IsRelPropertyReferenced(relProperty) || (relProperty.ToEnd.RelationshipMultiplicity == RelationshipMultiplicity.Many), "Unreferenced rel property? " + relProperty); // Handle N:1 if ((relProperty.FromEnd.RelationshipMultiplicity == RelationshipMultiplicity.Many) && (relProperty.ToEnd.RelationshipMultiplicity != RelationshipMultiplicity.Many)) { return RewriteManyToOneNavigationProperty(relProperty, sourceEntityNode, resultType); } // // Find the list of all relationships that could satisfy this relationship // If we find no matching relationship set, simply return a null node / empty collection // var relationshipSets = GetRelationshipSets(relProperty.Relationship); if (relationshipSets.Count == 0) { // return an empty set / null node if (relProperty.ToEnd.RelationshipMultiplicity == RelationshipMultiplicity.Many) { return m_command.CreateNode(m_command.CreateNewMultisetOp(resultType)); } return m_command.CreateNode(m_command.CreateNullOp(resultType)); } // Build out a ref over the source entity var sourceRefNode = m_command.CreateNode( m_command.CreateGetEntityRefOp(relProperty.FromEnd.TypeUsage), sourceEntityNode); // Hanlde the 1:M and N:M cases if (relProperty.ToEnd.RelationshipMultiplicity == RelationshipMultiplicity.Many) { // Handle N:M if (relProperty.FromEnd.RelationshipMultiplicity == RelationshipMultiplicity.Many) { return RewriteManyToManyNavigationProperty(relProperty, relationshipSets, sourceRefNode); } // Handle 1:M return RewriteOneToManyNavigationProperty(relProperty, relationshipSets, sourceRefNode); } // Handle 1:1 return RewriteOneToOneNavigationProperty(relProperty, relationshipSets, sourceRefNode); }
/// <summary> /// Gets the collection of properties that are on the principal end of a referential constraint for the specified navigation property. /// Requires: The association has a referential constraint. /// </summary> public ReadOnlyMetadataCollection<EdmProperty> GetPrincipalProperties(NavigationProperty navProperty) { if (navProperty == null) { throw new ArgumentNullException("navProperty"); } return ((AssociationType)navProperty.RelationshipType).ReferentialConstraints[0].FromProperties; }
private static bool IsModifed(NavigationProperty navigationProperty, IEnumerable<string> modifiedMembers) { var association = navigationProperty.RelationshipType as AssociationType; if (association == null) return false; var referentialConstraint = association.ReferentialConstraints.FirstOrDefault(); if (referentialConstraint == null) return false; var toProperties = referentialConstraint .ToProperties .Select(p => p.Name) .ToList(); return modifiedMembers.Intersect(toProperties).Any(); }
/// <summary> /// Constrcut a new member mapping metadata object /// </summary> /// <param name="edmNavigationProperty"></param> /// <param name="clrNavigationProperty"></param> internal ObjectNavigationPropertyMapping(NavigationProperty edmNavigationProperty, NavigationProperty clrNavigationProperty) : base(edmNavigationProperty, clrNavigationProperty) { }
internal void ResolveNavigationProperty(StructuralType declaringType, PropertyInfo propertyInfo) { Debug.Assert(propertyInfo.IsDefined(typeof(EdmRelationshipNavigationPropertyAttribute), false), "The property must have navigation property defined"); // EdmScalarPropertyAttribute, EdmComplexPropertyAttribute and EdmRelationshipNavigationPropertyAttribute // are all EdmPropertyAttributes that we need to process. If the current property is not an EdmPropertyAttribute // we will just ignore it and skip to the next property. object[] relationshipPropertyAttributes = propertyInfo.GetCustomAttributes(typeof(EdmRelationshipNavigationPropertyAttribute), false); Debug.Assert(relationshipPropertyAttributes.Length == 1, "There should be exactly one property for every navigation property"); // The only valid return types from navigation properties are: // (1) EntityType // (2) CollectionType containing valid EntityType // If TryGetLoadedType returned false, it could mean that we couldn't validate any part of the type, or it could mean that it's a generic // where the main generic type was validated, but the generic type parameter was not. We can't tell the difference, so just fail // with the same error message in both cases. The user will have to figure out which part of the type is wrong. // We can't just rely on checking for a generic because it can lead to a scenario where we report that the type parameter is invalid // when really it's the main generic type. That is more confusing than reporting the full name and letting the user determine the problem. EdmType propertyType; if (!TryGetLoadedType(propertyInfo.PropertyType, out propertyType) || !(propertyType.BuiltInTypeKind == BuiltInTypeKind.EntityType || propertyType.BuiltInTypeKind == BuiltInTypeKind.CollectionType)) { // Once an error is detected the property does not need to be validated further, just add to the errors // collection and continue with the next property. The failure will cause an exception to be thrown later during validation of all of the types. SessionData.EdmItemErrors.Add(new EdmItemError(System.Data.Entity.Strings.Validator_OSpace_InvalidNavPropReturnType(propertyInfo.Name, propertyInfo.DeclaringType.FullName, propertyInfo.PropertyType.FullName), null)); return; } // else we have a valid EntityType or CollectionType that contains EntityType. ResolveNonSchemaType enforces that a collection type // must contain an EntityType, and if it doesn't, propertyType will be null here. If propertyType is EntityType or CollectionType we know it is valid // Expecting EdmRelationshipNavigationPropertyAttribute to have AllowMultiple=False, so only look at first element in the attribute array EdmRelationshipNavigationPropertyAttribute attribute = (EdmRelationshipNavigationPropertyAttribute)relationshipPropertyAttributes[0]; EdmMember member = null; EdmType type; if (SessionData.TypesInLoading.TryGetValue(attribute.RelationshipNamespaceName + "." + attribute.RelationshipName, out type) && Helper.IsAssociationType(type)) { AssociationType relationshipType = (AssociationType)type; if (relationshipType != null) { // The return value of this property has been verified, so create the property now NavigationProperty navigationProperty = new NavigationProperty(propertyInfo.Name, TypeUsage.Create(propertyType), propertyInfo); navigationProperty.RelationshipType = relationshipType; member = navigationProperty; if (relationshipType.Members[0].Name == attribute.TargetRoleName) { navigationProperty.ToEndMember = (RelationshipEndMember)relationshipType.Members[0]; navigationProperty.FromEndMember = (RelationshipEndMember)relationshipType.Members[1]; } else if (relationshipType.Members[1].Name == attribute.TargetRoleName) { navigationProperty.ToEndMember = (RelationshipEndMember)relationshipType.Members[1]; navigationProperty.FromEndMember = (RelationshipEndMember)relationshipType.Members[0]; } else { SessionData.EdmItemErrors.Add(new EdmItemError(System.Data.Entity.Strings.TargetRoleNameInNavigationPropertyNotValid( propertyInfo.Name, propertyInfo.DeclaringType.FullName, attribute.TargetRoleName, attribute.RelationshipName), navigationProperty)); member = null; } if (member != null && ((RefType)navigationProperty.FromEndMember.TypeUsage.EdmType).ElementType.ClrType != declaringType.ClrType) { SessionData.EdmItemErrors.Add(new EdmItemError(System.Data.Entity.Strings.NavigationPropertyRelationshipEndTypeMismatch( declaringType.FullName, navigationProperty.Name, relationshipType.FullName, navigationProperty.FromEndMember.Name, ((RefType)navigationProperty.FromEndMember.TypeUsage.EdmType).ElementType.ClrType), navigationProperty)); member = null; } } } else { SessionData.EdmItemErrors.Add(new EdmItemError(System.Data.Entity.Strings.RelationshipNameInNavigationPropertyNotValid( propertyInfo.Name, propertyInfo.DeclaringType.FullName, attribute.RelationshipName), declaringType)); } if (member != null) { declaringType.AddMember(member); } }
/// <summary> /// Returns a unique association name for the specified navigation property. /// </summary> /// <param name="navigationProperty">The navigation property</param> /// <param name="foreignKeyRoleName">The foreign key role name for the property's association</param> /// <returns>A unique association name for the specified navigation property.</returns> private string GetAssociationName(NavigationProperty navigationProperty, string foreignKeyRoleName) { RelationshipEndMember fromMember = navigationProperty.FromEndMember; RelationshipEndMember toMember = navigationProperty.ToEndMember; RefType toRefType = toMember.TypeUsage.EdmType as RefType; EntityType toEntityType = toRefType.ElementType as EntityType; RefType fromRefType = fromMember.TypeUsage.EdmType as RefType; EntityType fromEntityType = fromRefType.ElementType as EntityType; bool isForeignKey = navigationProperty.FromEndMember.Name == foreignKeyRoleName; string fromTypeName = isForeignKey ? fromEntityType.Name : toEntityType.Name; string toTypeName = isForeignKey ? toEntityType.Name : fromEntityType.Name; // names are always formatted non-FK side type name followed by FK side type name string associationName = String.Format(CultureInfo.InvariantCulture, "{0}_{1}", toTypeName, fromTypeName); associationName = MakeUniqueName(associationName, _associationMap.Values.Select(p => p.Name)); return associationName; }
/// <summary> /// Attempts to get the property name for the assoication between the two given end /// names. Note that this property may not exist if a navigation property is defined /// in one direction but not in the other. /// </summary> /// <param name="relationshipType">the relationship for which a nav property is required</param> /// <param name="fromName">the 'from' end of the association</param> /// <param name="toName">the 'to' end of the association</param> /// <param name="navigationProperty">the property name, or null if none was found</param> /// <returns>true if a property was found, false otherwise</returns> internal bool TryGetNavigationProperty( string relationshipType, string fromName, string toName, out NavigationProperty navigationProperty) { // This is a linear search but it's probably okay because the number of entries // is generally small and this method is only called to generate code during lighweight // code gen. foreach (var navProperty in NavigationProperties) { if (navProperty.RelationshipType.FullName == relationshipType && navProperty.FromEndMember.Name == fromName && navProperty.ToEndMember.Name == toName) { navigationProperty = navProperty; return true; } } navigationProperty = null; return false; }
/// <summary> /// Attempts to get the property name for the ----oication between the two given end /// names. Note that this property may not exist if a navigation property is defined /// in one direction but not in the other. /// </summary> /// <param name="relationshipType">the relationship for which a nav property is required</param> /// <param name="fromName">the 'from' end of the association</param> /// <param name="toName">the 'to' end of the association</param> /// <param name="navigationProperty">the property name, or null if none was found</param> /// <returns>true if a property was found, false otherwise</returns> internal bool TryGetNavigationProperty(string relationshipType, string fromName, string toName, out NavigationProperty navigationProperty) { // This is a linear search but it's probably okay because the number of entries // is generally small and this method is only called to generate code during lighweight // code gen. foreach (NavigationProperty navProperty in NavigationProperties) { if (navProperty.RelationshipType.FullName == relationshipType && navProperty.FromEndMember.Name == fromName && navProperty.ToEndMember.Name == toName) { navigationProperty = navProperty; return(true); } } navigationProperty = null; return(false); }
protected override void Visit(NavigationProperty navigationProperty) { // navigation properties are not considered in view generation return; }
/// <summary> /// Gets the type of entity or entities at the target end of the given navigation property. /// </summary> /// <param name = "navigationProperty">The navigation property.</param> /// <returns>The CLR type of the entity or entities at the other end.</returns> private Type GetNavigationTargetType(NavigationProperty navigationProperty) { var metadataWorkspace = _internalContext.ObjectContext.MetadataWorkspace; var cSpaceType = navigationProperty.RelationshipType.RelationshipEndMembers.Single( e => navigationProperty.ToEndMember.Name == e.Name). GetEntityType(); var oSpaceType = metadataWorkspace.GetObjectSpaceType(cSpaceType); var objectItemCollection = (ObjectItemCollection)metadataWorkspace.GetItemCollection(DataSpace.OSpace); return objectItemCollection.GetClrType(oSpaceType); }
/// <summary> /// Creates an AssociationAttribute for the specified navigation property /// </summary> /// <param name="navigationProperty">The navigation property that corresponds to the association (it identifies the end points)</param> /// <returns>A new AssociationAttribute that describes the given navigation property association</returns> internal AssociationAttribute CreateAssociationAttribute(NavigationProperty navigationProperty) { AssociationInfo assocInfo = GetAssociationInfo(navigationProperty); bool isForeignKey = navigationProperty.FromEndMember.Name == assocInfo.FKRole; string thisKey; string otherKey; if (isForeignKey) { thisKey = String.Join(",", assocInfo.ThisKey); otherKey = String.Join(",", assocInfo.OtherKey); } else { otherKey = String.Join(",", assocInfo.ThisKey); thisKey = String.Join(",", assocInfo.OtherKey); } AssociationAttribute assocAttrib = new AssociationAttribute(assocInfo.Name, thisKey, otherKey); assocAttrib.IsForeignKey = isForeignKey; return assocAttrib; }
private void CreateModelNavigationProperty(LoadMethodSessionState session, AssociationEndMember from, AssociationEndMember to) { EntityType entityType = (EntityType)((RefType)from.TypeUsage.EdmType).ElementType; UniqueIdentifierService usedMemberNames = new UniqueIdentifierService(false); LoadNameLookupWithUsedMemberNames(entityType, usedMemberNames); string name = CreateModelName(this._pluralizationServiceHandler.GetNavigationPropertyName(to, to.Name), usedMemberNames); NavigationProperty navigationProperty = new NavigationProperty(name, to.TypeUsage); navigationProperty.RelationshipType = (AssociationType)to.DeclaringType; navigationProperty.ToEndMember = to; navigationProperty.FromEndMember = from; entityType.AddMember(navigationProperty); }
/// <summary> /// /// </summary> /// <param name="generator"></param> /// <param name="navigationProperty"></param> public NavigationPropertyEmitter(ClientApiGenerator generator, NavigationProperty navigationProperty, bool declaringTypeUsesStandardBaseType) : base(generator, navigationProperty, declaringTypeUsesStandardBaseType) { }
/// <summary> /// Dumps the specified Navigation Property EdmMember metadata instance with the specified decoration /// </summary> /// <param name="navProp">The Navigation Property metadata to dump</param> /// <param name="name">The decorating block name</param> internal void Dump(NavigationProperty navProp, string name) { Begin(name); Begin( "NavigationProperty", "Name", navProp.Name, //"IsParent", end.IsParent, "RelationshipTypeName", navProp.RelationshipType.FullName, "ToEndMemberName", navProp.ToEndMember.Name ); Dump(navProp.DeclaringType, "DeclaringType"); Dump(navProp.TypeUsage, "PropertyType"); End("NavigationProperty"); End(name); }
protected EntityDataSourceReferenceValueColumn(MetadataWorkspace ocWorkspace, NavigationProperty navigationProperty) : base(EntityDataSourceUtil.CheckArgumentNull(navigationProperty, "navigationProperty").Name) { EntityDataSourceUtil.CheckArgumentNull(ocWorkspace, "ocWorkspace"); this.navigationProperty = navigationProperty; }
/// <summary> /// Returns the NavigationProperty that is the other end of the same association set if it is /// available, otherwise it returns null. /// </summary> public NavigationProperty Inverse(NavigationProperty navProperty) { if (navProperty == null) { return null; } EntityType toEntity = navProperty.ToEndMember.GetEntityType(); return toEntity.NavigationProperties .SingleOrDefault(n => Object.ReferenceEquals(n.RelationshipType, navProperty.RelationshipType) && !Object.ReferenceEquals(n, navProperty)); }
internal static IEnumerable<string> GetDependentPropertyNames(NavigationProperty navigationProperty, bool checkRelationshipType) { if (checkRelationshipType) { if (navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne && navigationProperty.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One) { // Get constraint when this association is on the "parent" (aka "from") side. This means // that the navProperty represents a Children association in a 1-1 relationship. For example, // this could be a Item-ItemDetail scenario where the ItemDetail table has a PK that is also an FK // into the Item table (thus ensuring the 1-1 cardinality). We need to special case this situation because normally we would try // to build a foreign key name of the form "Item.ItemID", but we want just "ItemID". AssociationType relationshipType = (AssociationType)navigationProperty.RelationshipType; ReferentialConstraint constraint = relationshipType.ReferentialConstraints.FirstOrDefault(c => c.ToRole == navigationProperty.ToEndMember); if (constraint != null) { return constraint.FromProperties.Select(p => p.Name); } // Fall back on the primary keys if no constraints were found but only if we are on the parent side. i.e the 1 side Item side in an Item-ItemDetail // Get the primary keys on the "from" side of the relationship. i.e Product.Category -> ProductID return navigationProperty.FromEndMember.GetEntityType().KeyMembers.Select(m => m.Name); } } return navigationProperty.GetDependentProperties().Select(m => m.Name); }
/// <summary> /// Retrieves the Entity (result or element) type produced by a Navigation Property. /// </summary> /// <param name="navProp">The navigation property</param> /// <returns> /// The Entity type produced by the navigation property. /// This may be the immediate result type (if the result is at most one) /// or the element type of the result type, otherwise. /// </returns> private static EntityType EntityTypeFromResultType(NavigationProperty navProp) { EntityType retType = null; TryGetEntityType(navProp.TypeUsage, out retType); // Currently, navigation properties may only return an Entity or Collection<Entity> result Debug.Assert(retType != null, "Navigation property has non-Entity and non-Entity collection result type?"); return retType; }
private static bool IsLoaded(AuditEntryState state, NavigationProperty navigationProperty, IMemberAccessor accessor) { var relationshipManager = state.ObjectStateEntry.RelationshipManager; var getEntityReference = _relatedAccessor.Value.MakeGenericMethod(accessor.MemberType); var parameters = new[] { navigationProperty.RelationshipType.FullName, navigationProperty.ToEndMember.Name }; var entityReference = getEntityReference.Invoke(relationshipManager, parameters) as EntityReference; return (entityReference != null && entityReference.IsLoaded); }
internal static EntityDataSourceReferenceValueColumn Create(Type clrToType, MetadataWorkspace ocWorkspace, NavigationProperty navigationProperty) { EntityDataSourceUtil.CheckArgumentNull(clrToType, "clrToType"); Type columnType = typeof(EntityDataSourceReferenceValueColumn<>).MakeGenericType(clrToType); EntityDataSourceReferenceValueColumn result = (EntityDataSourceReferenceValueColumn)Activator.CreateInstance(columnType, ocWorkspace, navigationProperty); return result; }
/// <summary> /// Utility method to retrieve the 'To' AssociationEndMember of a NavigationProperty /// </summary> /// <param name="property">The navigation property</param> /// <returns>The AssociationEndMember that is the target of the navigation operation represented by the NavigationProperty</returns> private AssociationEndMember GetNavigationPropertyTargetEnd(NavigationProperty property) { AssociationType relationship = this.Metadata.GetItem<AssociationType>(property.RelationshipType.FullName, DataSpace.CSpace); Debug.Assert(relationship.AssociationEndMembers.Contains(property.ToEndMember.Name), "Association does not declare member referenced by Navigation property?"); return relationship.AssociationEndMembers[property.ToEndMember.Name]; }
private static bool IsZeroOrOne(NavigationProperty navigationProperty) { return (navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne && navigationProperty.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One) || (navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One && navigationProperty.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne); }
private void EmitReferenceProperty(TypeBuilder typeBuilder, PropertyBuilder propertyBuilder, PropertyInfo baseProperty, NavigationProperty navProperty) { const MethodAttributes methodAttributes = MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.Virtual; MethodInfo baseSetter = baseProperty.GetSetMethod(true); ; MethodAttributes methodAccess = baseSetter.Attributes & MethodAttributes.MemberAccessMask; MethodInfo specificGetRelatedReference = s_GetRelatedReference.MakeGenericMethod(baseProperty.PropertyType); MethodInfo specificEntityReferenceSetValue = typeof(EntityReference<>).MakeGenericType(baseProperty.PropertyType).GetMethod("set_Value"); ; MethodBuilder setterBuilder = typeBuilder.DefineMethod("set_" + baseProperty.Name, methodAccess | methodAttributes, null, new Type[] { baseProperty.PropertyType }); ILGenerator generator = setterBuilder.GetILGenerator(); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Callvirt, _getRelationshipManager); generator.Emit(OpCodes.Ldstr, navProperty.RelationshipType.FullName); generator.Emit(OpCodes.Ldstr, navProperty.ToEndMember.Name); generator.Emit(OpCodes.Callvirt, specificGetRelatedReference); generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Callvirt, specificEntityReferenceSetValue); generator.Emit(OpCodes.Ret); propertyBuilder.SetSetMethod(setterBuilder); _referenceProperties.Add(new KeyValuePair<NavigationProperty,PropertyInfo>(navProperty, baseProperty)); }
internal static IEnumerable<string> GetDependentPropertyNames(NavigationProperty navigationProperty) { return GetDependentPropertyNames(navigationProperty, true /*checkRelationshipType*/); }
private void EmitCollectionProperty(TypeBuilder typeBuilder, PropertyBuilder propertyBuilder, PropertyInfo baseProperty, NavigationProperty navProperty) { const MethodAttributes methodAttributes = MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.Virtual; MethodInfo baseSetter = baseProperty.GetSetMethod(true); ; MethodAttributes methodAccess = baseSetter.Attributes & MethodAttributes.MemberAccessMask; string cannotSetException = System.Data.Entity.Strings.EntityProxyTypeInfo_CannotSetEntityCollectionProperty(propertyBuilder.Name, typeBuilder.Name); MethodBuilder setterBuilder = typeBuilder.DefineMethod("set_" + baseProperty.Name, methodAccess | methodAttributes, null, new Type[] { baseProperty.PropertyType }); ILGenerator generator = setterBuilder.GetILGenerator(); Label instanceEqual = generator.DefineLabel(); generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Call, _getRelationshipManager); generator.Emit(OpCodes.Ldstr, navProperty.RelationshipType.FullName); generator.Emit(OpCodes.Ldstr, navProperty.ToEndMember.Name); generator.Emit(OpCodes.Callvirt, s_GetRelatedEnd); generator.Emit(OpCodes.Beq_S, instanceEqual); generator.Emit(OpCodes.Ldstr, cannotSetException); generator.Emit(OpCodes.Newobj, s_InvalidOperationConstructor); generator.Emit(OpCodes.Throw); generator.MarkLabel(instanceEqual); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Call, baseProperty.GetSetMethod(true)); generator.Emit(OpCodes.Ret); propertyBuilder.SetSetMethod(setterBuilder); _collectionProperties.Add(new KeyValuePair<NavigationProperty, PropertyInfo>(navProperty, baseProperty)); }