/// <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; }); }
public void Can_get_and_set_configuration_facet() { var navigationProperty = new NavigationProperty("N", TypeUsage.Create(new EntityType("E", "N", DataSpace.CSpace))); navigationProperty.SetConfiguration(42); Assert.Equal(42, navigationProperty.GetConfiguration()); }
public void Apply_is_noop_when_existing_constraint() { var associationType = new AssociationType("A", XmlConstants.ModelNamespace_3, false, DataSpace.CSpace); associationType.SourceEnd = new AssociationEndMember("S", new EntityType("E", "N", DataSpace.CSpace)); associationType.TargetEnd = new AssociationEndMember("T", new EntityType("E", "N", DataSpace.CSpace)); var property = EdmProperty.Primitive("Fk", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String)); var associationConstraint = new ReferentialConstraint( associationType.SourceEnd, associationType.TargetEnd, new[] { property }, new[] { property }); associationType.Constraint = associationConstraint; var navigationProperty = new NavigationProperty("N", TypeUsage.Create(new EntityType("E", "N", DataSpace.CSpace))) { RelationshipType = associationType }; ((IEdmConvention<NavigationProperty>)new ForeignKeyNavigationPropertyAttributeConvention()) .Apply(navigationProperty, new EdmModel(DataSpace.CSpace)); Assert.Same(associationConstraint, navigationProperty.Association.Constraint); }
public IEnumerable<IFilterAttribute> AttributesFor(NavigationProperty property) { return withCache(new Signature(property), () => { var info = mapper.Map(property); return info.GetAttributes<IFilterAttribute>(); }); }
internal void WriteNavigationPropertyElementHeader(NavigationProperty member) { _xmlWriter.WriteStartElement(XmlConstants.NavigationProperty); _xmlWriter.WriteAttributeString(XmlConstants.Name, member.Name); _xmlWriter.WriteAttributeString( XmlConstants.Relationship, GetQualifiedTypeName(XmlConstants.Self, member.Association.Name)); _xmlWriter.WriteAttributeString(XmlConstants.FromRole, member.GetFromEnd().Name); _xmlWriter.WriteAttributeString(XmlConstants.ToRole, member.ToEndMember.Name); }
internal void ResolveNavigationProperty(StructuralType declaringType, PropertyInfo propertyInfo) { IEnumerable <EdmRelationshipNavigationPropertyAttribute> customAttributes = propertyInfo.GetCustomAttributes <EdmRelationshipNavigationPropertyAttribute>(false); EdmType edmType; if (!this.TryGetLoadedType(propertyInfo.PropertyType, out edmType) || edmType.BuiltInTypeKind != BuiltInTypeKind.EntityType && edmType.BuiltInTypeKind != BuiltInTypeKind.CollectionType) { this.SessionData.EdmItemErrors.Add(new EdmItemError(Strings.Validator_OSpace_InvalidNavPropReturnType((object)propertyInfo.Name, (object)propertyInfo.DeclaringType.FullName, (object)propertyInfo.PropertyType.FullName))); } else { EdmRelationshipNavigationPropertyAttribute propertyAttribute = customAttributes.First <EdmRelationshipNavigationPropertyAttribute>(); EdmMember member = (EdmMember)null; EdmType type; if (this.SessionData.TypesInLoading.TryGetValue(propertyAttribute.RelationshipNamespaceName + "." + propertyAttribute.RelationshipName, out type) && Helper.IsAssociationType(type)) { AssociationType associationType = (AssociationType)type; if (associationType != null) { NavigationProperty navigationProperty = new NavigationProperty(propertyInfo.Name, TypeUsage.Create(edmType)); navigationProperty.RelationshipType = (RelationshipType)associationType; member = (EdmMember)navigationProperty; if (associationType.Members[0].Name == propertyAttribute.TargetRoleName) { navigationProperty.ToEndMember = (RelationshipEndMember)associationType.Members[0]; navigationProperty.FromEndMember = (RelationshipEndMember)associationType.Members[1]; } else if (associationType.Members[1].Name == propertyAttribute.TargetRoleName) { navigationProperty.ToEndMember = (RelationshipEndMember)associationType.Members[1]; navigationProperty.FromEndMember = (RelationshipEndMember)associationType.Members[0]; } else { this.SessionData.EdmItemErrors.Add(new EdmItemError(Strings.TargetRoleNameInNavigationPropertyNotValid((object)propertyInfo.Name, (object)propertyInfo.DeclaringType.FullName, (object)propertyAttribute.TargetRoleName, (object)propertyAttribute.RelationshipName))); member = (EdmMember)null; } if (member != null && ((RefType)navigationProperty.FromEndMember.TypeUsage.EdmType).ElementType.ClrType != declaringType.ClrType) { this.SessionData.EdmItemErrors.Add(new EdmItemError(Strings.NavigationPropertyRelationshipEndTypeMismatch((object)declaringType.FullName, (object)navigationProperty.Name, (object)associationType.FullName, (object)navigationProperty.FromEndMember.Name, (object)((RefType)navigationProperty.FromEndMember.TypeUsage.EdmType).ElementType.ClrType))); member = (EdmMember)null; } } } else { this.SessionData.EdmItemErrors.Add(new EdmItemError(Strings.RelationshipNameInNavigationPropertyNotValid((object)propertyInfo.Name, (object)propertyInfo.DeclaringType.FullName, (object)propertyAttribute.RelationshipName))); } if (member == null) { return; } declaringType.AddMember(member); } }
public void Apply_is_noop_when_no_fk_annotation() { var navigationProperty = new NavigationProperty("N", TypeUsage.Create(new EntityType("E", "N", DataSpace.CSpace))) { RelationshipType = new AssociationType("A", XmlConstants.ModelNamespace_3, false, DataSpace.CSpace) }; ((IEdmConvention<NavigationProperty>)new ForeignKeyNavigationPropertyAttributeConvention()) .Apply(navigationProperty, new EdmModel(DataSpace.CSpace)); Assert.Null(navigationProperty.Association.Constraint); }
public void Configure_should_set_configuration_annotations() { var navigationPropertyConfiguration = new NavigationPropertyConfiguration(new MockPropertyInfo()); var navigationProperty = new NavigationProperty("N", TypeUsage.Create(new EntityType())) { RelationshipType = new AssociationType() }; navigationProperty.Association.SourceEnd = new AssociationEndMember("S", new EntityType()); navigationProperty.Association.TargetEnd = new AssociationEndMember("T", new EntityType()); navigationPropertyConfiguration.Configure(navigationProperty, new EdmModel(), new EntityTypeConfiguration(typeof(object))); Assert.NotNull(navigationProperty.GetConfiguration()); Assert.NotNull(navigationProperty.Association.GetConfiguration()); }
public void EdmNavigationProperty_BadNavigationPropertyBadFromRoleType() { var parentEntity = new EntityType("P", "N", DataSpace.CSpace); var targetEntity = new EntityType("T", "N", DataSpace.CSpace); var sourceEntity = new EntityType("S", "N", DataSpace.CSpace); var associationType = new AssociationType("A", XmlConstants.ModelNamespace_3, false, DataSpace.CSpace) { SourceEnd = new AssociationEndMember("S", sourceEntity), TargetEnd = new AssociationEndMember("T", targetEntity) }; var navigationProperty = new NavigationProperty("N", TypeUsage.Create(targetEntity)) { RelationshipType = associationType }; parentEntity.AddMember(navigationProperty); var model = new EdmModel(DataSpace.CSpace); model.AddItem(parentEntity); var validationContext = new EdmModelValidationContext(model, true); DataModelErrorEventArgs errorEventArgs = null; validationContext.OnError += (_, e) => errorEventArgs = e; EdmModelSemanticValidationRules .EdmNavigationProperty_BadNavigationPropertyBadFromRoleType .Evaluate(validationContext, navigationProperty); Assert.NotNull(errorEventArgs); Assert.Same(navigationProperty, errorEventArgs.Item); Assert.Equal( Strings.BadNavigationPropertyBadFromRoleType( navigationProperty.Name, sourceEntity.Name, navigationProperty.GetFromEnd().Name, navigationProperty.Association.Name, parentEntity.Name), errorEventArgs.ErrorMessage); }
/// <summary> /// Creates a NavigationProperty instance from the specified parameters. /// </summary> /// <param name="name">The name of the navigation property.</param> /// <param name="typeUsage">Specifies the navigation property type and its facets.</param> /// <param name="relationshipType">The relationship type for the navigation.</param> /// <param name="from">The source end member in the navigation.</param> /// <param name="to">The target end member in the navigation.</param> /// <returns>The newly created NavigationProperty instance.</returns> public static NavigationProperty Create( string name, TypeUsage typeUsage, RelationshipType relationshipType, RelationshipEndMember from, RelationshipEndMember to) { var instance = new NavigationProperty(name, typeUsage); instance.RelationshipType = relationshipType; instance.FromEndMember = from; instance.ToEndMember = to; instance.SetReadOnly(); return(instance); }
public IFluentConfiguration Discover(NavigationProperty navigationProperty, DbModel model) { Debug.Assert(navigationProperty != null, "navigationProperty is null."); Debug.Assert(model != null, "model is null."); var associationType = (AssociationType)navigationProperty.RelationshipType; if (!associationType.IsForeignKey || (navigationProperty.ToEndMember.RelationshipMultiplicity != RelationshipMultiplicity.Many && navigationProperty.FromEndMember.RelationshipMultiplicity != RelationshipMultiplicity.Many)) { // Doesn't apply return null; } var constraint = associationType.Constraint; var entityType = (EntityType)navigationProperty.DeclaringType; var fromProperty = constraint.FromProperties.First(); var fromPropertyName = fromProperty.Name; var toEntityType = navigationProperty.ToEndMember.GetEntityType(); // NOTE: OrderBy works around a bug in primary key column ordering (Work Item 868) var toProperties = constraint.ToProperties.OrderBy( p => entityType.KeyMembers.IndexOf(constraint.FromProperties[constraint.ToProperties.IndexOf(p)])); var toPropertyName = toProperties.First().Name; if (!toProperties.MoreThan(1) && (toPropertyName.EqualsIgnoreCase(navigationProperty.Name + fromPropertyName) || (!entityType.NavigationProperties.Where(p => p.ToEndMember.GetEntityType() == toEntityType) .MoreThan(1) && (toPropertyName.EqualsIgnoreCase(fromPropertyName) || toPropertyName.EqualsIgnoreCase(fromProperty.DeclaringType.Name + fromPropertyName))))) { // By convention return null; } var configuration = new ForeignKeyConfiguration(); foreach (var property in toProperties) { configuration.Properties.Add(property); } return configuration; }
internal bool TryGetNavigationProperty( string relationshipType, string fromName, string toName, out NavigationProperty navigationProperty) { foreach (NavigationProperty navigationProperty1 in this.NavigationProperties) { if (navigationProperty1.RelationshipType.FullName == relationshipType && navigationProperty1.FromEndMember.Name == fromName && navigationProperty1.ToEndMember.Name == toName) { navigationProperty = navigationProperty1; return(true); } } navigationProperty = (NavigationProperty)null; return(false); }
public void Configure_should_set_configuration_annotations() { var navigationPropertyConfiguration = new NavigationPropertyConfiguration(new MockPropertyInfo(typeof(AType1), "N")); var navigationProperty = new NavigationProperty("N", TypeUsage.Create(new EntityType("E", "N", DataSpace.CSpace))) { RelationshipType = new AssociationType("A", XmlConstants.ModelNamespace_3, false, DataSpace.CSpace) }; navigationProperty.Association.SourceEnd = new AssociationEndMember("S", new EntityType("E", "N", DataSpace.CSpace)); navigationProperty.Association.TargetEnd = new AssociationEndMember("T", new EntityType("E", "N", DataSpace.CSpace)); navigationPropertyConfiguration.Configure( navigationProperty, new EdmModel(DataSpace.CSpace), new EntityTypeConfiguration(typeof(object))); Assert.NotNull(navigationProperty.GetConfiguration()); Assert.NotNull(navigationProperty.Association.GetConfiguration()); }
public void Apply_is_noop_when_unknown_dependent() { var model = new EdmModel(DataSpace.CSpace); var associationType = new AssociationType("A", XmlConstants.ModelNamespace_3, false, DataSpace.CSpace); associationType.SourceEnd = new AssociationEndMember("S", new EntityType("E", "N", DataSpace.CSpace)); associationType.TargetEnd = new AssociationEndMember("T", new EntityType("E", "N", DataSpace.CSpace)); var navigationProperty = new NavigationProperty("N", TypeUsage.Create(associationType.TargetEnd.GetEntityType())) { RelationshipType = associationType }; var foreignKeyAnnotation = new ForeignKeyAttribute("AId"); navigationProperty.Annotations.SetClrAttributes(new[] { foreignKeyAnnotation }); ((IEdmConvention<NavigationProperty>)new ForeignKeyNavigationPropertyAttributeConvention()) .Apply(navigationProperty, model); Assert.Null(associationType.Constraint); }
/// <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) { var assocInfo = GetAssociationInfo(navigationProperty); var 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); } return new AssociationAttribute(assocInfo.Name, thisKey, otherKey) { IsForeignKey = isForeignKey }; }
private static NavigationProperty ConvertToNavigationProperty( EntityType declaringEntityType, System.Data.Entity.Core.SchemaObjectModel.NavigationProperty somNavigationProperty, DbProviderManifest providerManifest, Converter.ConversionCache convertedItemCache, Dictionary <SchemaElement, GlobalItem> newGlobalItems) { EntityType endMemberType = (EntityType)Converter.LoadSchemaElement(somNavigationProperty.Type, providerManifest, convertedItemCache, newGlobalItems); AssociationType associationType = (AssociationType)Converter.LoadSchemaElement((System.Data.Entity.Core.SchemaObjectModel.SchemaType)somNavigationProperty.Relationship, providerManifest, convertedItemCache, newGlobalItems); IRelationshipEnd end = (IRelationshipEnd)null; somNavigationProperty.Relationship.TryGetEnd(somNavigationProperty.ToEnd.Name, out end); RelationshipMultiplicity?multiplicity1 = end.Multiplicity; EdmType edmType = (multiplicity1.GetValueOrDefault() != RelationshipMultiplicity.Many ? 0 : (multiplicity1.HasValue ? 1 : 0)) == 0 ? (EdmType)endMemberType : (EdmType)endMemberType.GetCollectionType(); RelationshipMultiplicity?multiplicity2 = end.Multiplicity; TypeUsage typeUsage; if ((multiplicity2.GetValueOrDefault() != RelationshipMultiplicity.One ? 0 : (multiplicity2.HasValue ? 1 : 0)) != 0) { typeUsage = TypeUsage.Create(edmType, new FacetValues() { Nullable = (FacetValueContainer <bool?>) new bool?(false) }); } else { typeUsage = TypeUsage.Create(edmType); } Converter.InitializeAssociationEndMember(associationType, somNavigationProperty.ToEnd, endMemberType); Converter.InitializeAssociationEndMember(associationType, somNavigationProperty.FromEnd, declaringEntityType); NavigationProperty navigationProperty = new NavigationProperty(somNavigationProperty.Name, typeUsage); navigationProperty.RelationshipType = (RelationshipType)associationType; navigationProperty.ToEndMember = (RelationshipEndMember)associationType.Members[somNavigationProperty.ToEnd.Name]; navigationProperty.FromEndMember = (RelationshipEndMember)associationType.Members[somNavigationProperty.FromEnd.Name]; if (somNavigationProperty.Documentation != null) { navigationProperty.Documentation = Converter.ConvertToDocumentation(somNavigationProperty.Documentation); } Converter.AddOtherContent((SchemaElement)somNavigationProperty, (MetadataItem)navigationProperty); return(navigationProperty); }
public void Nullability_updated_when_property_goes_readonly() { var navigationProperty = new NavigationProperty("N", TypeUsage.Create(new EntityType("E", "N", DataSpace.CSpace))) { ToEndMember = new AssociationEndMember( "T", new RefType(new EntityType("E", "N", DataSpace.CSpace)), RelationshipMultiplicity.ZeroOrOne) }; Assert.Equal(true, navigationProperty.TypeUsage.Facets[EdmConstants.Nullable].Value); navigationProperty.ToEndMember.RelationshipMultiplicity = RelationshipMultiplicity.One; Assert.Equal(true, navigationProperty.TypeUsage.Facets[EdmConstants.Nullable].Value); navigationProperty.SetReadOnly(); Assert.Equal(false, navigationProperty.TypeUsage.Facets[EdmConstants.Nullable].Value); }
private void ConfigureDependentBehavior( AssociationType associationType, EdmModel model, EntityTypeConfiguration entityTypeConfiguration) { AssociationEndMember principalEnd; AssociationEndMember dependentEnd; if (!associationType.TryGuessPrincipalAndDependentEnds(out principalEnd, out dependentEnd)) { if (this.IsNavigationPropertyDeclaringTypePrincipal.HasValue) { associationType.MarkPrincipalConfigured(); System.Data.Entity.Core.Metadata.Edm.NavigationProperty navigationProperty = model.EntityTypes.SelectMany <EntityType, System.Data.Entity.Core.Metadata.Edm.NavigationProperty>((Func <EntityType, IEnumerable <System.Data.Entity.Core.Metadata.Edm.NavigationProperty> >)(et => (IEnumerable <System.Data.Entity.Core.Metadata.Edm.NavigationProperty>)et.DeclaredNavigationProperties)).Single <System.Data.Entity.Core.Metadata.Edm.NavigationProperty>((Func <System.Data.Entity.Core.Metadata.Edm.NavigationProperty, bool>)(np => { if (np.RelationshipType.Equals((object)associationType)) { return(np.GetClrPropertyInfo().IsSameAs(this.NavigationProperty)); } return(false); })); principalEnd = this.IsNavigationPropertyDeclaringTypePrincipal.Value ? associationType.GetOtherEnd(navigationProperty.ResultEnd) : navigationProperty.ResultEnd; dependentEnd = associationType.GetOtherEnd(principalEnd); if (associationType.SourceEnd != principalEnd) { associationType.SourceEnd = principalEnd; associationType.TargetEnd = dependentEnd; AssociationSet associationSet = model.Containers.SelectMany <EntityContainer, AssociationSet>((Func <EntityContainer, IEnumerable <AssociationSet> >)(ct => (IEnumerable <AssociationSet>)ct.AssociationSets)).Single <AssociationSet>((Func <AssociationSet, bool>)(aset => aset.ElementType == associationType)); EntitySet sourceSet = associationSet.SourceSet; associationSet.SourceSet = associationSet.TargetSet; associationSet.TargetSet = sourceSet; } } if (principalEnd == null) { dependentEnd = associationType.TargetEnd; } } this.ConfigureConstraint(associationType, dependentEnd, entityTypeConfiguration); this.ConfigureDeleteAction(associationType.GetOtherEnd(dependentEnd)); }
// <summary> // Attempts to get the property name for the association 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 lightweight // 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); }
internal void Configure( System.Data.Entity.Core.Metadata.Edm.NavigationProperty navigationProperty, EdmModel model, EntityTypeConfiguration entityTypeConfiguration) { navigationProperty.SetConfiguration((object)this); AssociationType association = navigationProperty.Association; NavigationPropertyConfiguration configuration = association.GetConfiguration() as NavigationPropertyConfiguration; if (configuration == null) { association.SetConfiguration((object)this); } else { this.EnsureConsistency(configuration); } this.ConfigureInverse(association, model); this.ConfigureEndKinds(association, configuration); this.ConfigureDependentBehavior(association, model, entityTypeConfiguration); }
public static MultiplicityConfiguration Discover(NavigationProperty navigationProperty, out bool isDefault) { Debug.Assert(navigationProperty != null, "navigationProperty is null."); var entityType = (EntityType)navigationProperty.DeclaringType; var otherEntityType = navigationProperty.ToEndMember.GetEntityType(); var otherNavigationProperty = otherEntityType.NavigationProperties.First( p => p.ToEndMember == navigationProperty.FromEndMember); isDefault = (navigationProperty.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many || otherNavigationProperty.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) && !entityType.NavigationProperties.Where(p => p.ToEndMember.GetEntityType() == otherEntityType) .MoreThan(1); return new MultiplicityConfiguration { LeftEntityType = entityType, LeftNavigationProperty = navigationProperty, RightNavigationProperty = otherNavigationProperty }; }
public void Can_get_list_of_declared_navigation_properties() { var entityType = new EntityType("E", "N", DataSpace.CSpace); Assert.Empty(entityType.DeclaredNavigationProperties); var property = new NavigationProperty("N", TypeUsage.Create(new EntityType("E", "N", DataSpace.CSpace))); entityType.AddMember(property); Assert.Equal(1, entityType.DeclaredNavigationProperties.Count); entityType.RemoveMember(property); var baseType = new EntityType("E", "N", DataSpace.CSpace); baseType.AddMember(property); entityType.BaseType = baseType; Assert.Empty(entityType.DeclaredNavigationProperties); Assert.Equal(1, entityType.Members.Count); }
public void NavigationProperties_is_thread_safe() { var entityType = new EntityType("E", "N", DataSpace.CSpace); var property = new NavigationProperty("N", TypeUsage.Create(new EntityType("E", "N", DataSpace.CSpace))); entityType.AddMember(property); const int cycles = 100; const int threadCount = 30; Action readNavigationProperties = () => { for (var i = 0; i < cycles; ++i) { var navProps = entityType.NavigationProperties; //touching Members.Source triggers a reset to NavigationProperties var sourceCount = entityType.Members.Source.Count; Assert.True(sourceCount == 1); var navigationPropertiesAfterReset = entityType.NavigationProperties; Assert.True(navProps != null, "First reference to NavigationProperties should not be null"); Assert.True(navigationPropertiesAfterReset != null, "Second reference to NavigationProperties should not be null"); Assert.False(ReferenceEquals(navProps, navigationPropertiesAfterReset), "The NavigationProperties instances should be different"); } }; var tasks = new List <Thread>(); for (var i = 0; i < threadCount; ++i) { tasks.Add(new Thread(new ThreadStart(readNavigationProperties))); } tasks.ForEach(t => t.Start()); tasks.ForEach(t => t.Join()); }
public static void Adding_a_NavigationProperty_to_an_EntityType_can_be_forced_when_read_only() { var typeUsage = TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String)); var associationType = new AssociationType("AssociationType", "Namespace", true, DataSpace.CSpace); var source = new EntityType("Source", "Namespace", DataSpace.CSpace); var target = new EntityType("Target", "Namespace", DataSpace.CSpace); var sourceEnd = new AssociationEndMember("SourceEnd", source); var targetEnd = new AssociationEndMember("TargetEnd", target); var navigationProperty = NavigationProperty.Create( "NavigationProperty", typeUsage, associationType, sourceEnd, targetEnd, null); source.SetReadOnly(); Assert.True(source.IsReadOnly); Assert.Equal( Resources.Strings.OperationOnReadOnlyItem, Assert.Throws <InvalidOperationException>( () => source.AddMember(navigationProperty)).Message); Assert.Equal(0, source.Members.Count); source.AddNavigationProperty(navigationProperty); Assert.True(source.IsReadOnly); Assert.Equal(1, source.Members.Count); Assert.Same(navigationProperty, source.Members[0]); Assert.Equal( Resources.Strings.OperationOnReadOnlyItem, Assert.Throws <InvalidOperationException>( () => source.AddMember(navigationProperty)).Message); }
/// <summary> /// Creates a NavigationProperty instance from the specified parameters. /// </summary> /// <param name="name">The name of the navigation property.</param> /// <param name="typeUsage">Specifies the navigation property type and its facets.</param> /// <param name="relationshipType">The relationship type for the navigation.</param> /// <param name="from">The source end member in the navigation.</param> /// <param name="to">The target end member in the navigation.</param> /// <param name="metadataProperties">The metadata properties of the navigation property.</param> /// <returns>The newly created NavigationProperty instance.</returns> public static NavigationProperty Create( string name, TypeUsage typeUsage, RelationshipType relationshipType, RelationshipEndMember from, RelationshipEndMember to, IEnumerable <MetadataProperty> metadataProperties) { Check.NotEmpty(name, nameof(name)); Check.NotNull <TypeUsage>(typeUsage, nameof(typeUsage)); NavigationProperty navigationProperty = new NavigationProperty(name, typeUsage); navigationProperty.RelationshipType = relationshipType; navigationProperty.FromEndMember = from; navigationProperty.ToEndMember = to; if (metadataProperties != null) { navigationProperty.AddMetadataProperties(metadataProperties.ToList <MetadataProperty>()); } navigationProperty.SetReadOnly(); return(navigationProperty); }
public void Can_get_list_of_declared_navigation_properties() { var entityType = new EntityType(); Assert.Empty(entityType.DeclaredNavigationProperties); var property = new NavigationProperty("N", TypeUsage.Create(new EntityType())); entityType.AddMember(property); Assert.Equal(1, entityType.DeclaredNavigationProperties.Count); entityType.RemoveMember(property); var baseType = new EntityType(); baseType.AddMember(property); entityType.BaseType = baseType; Assert.Empty(entityType.DeclaredNavigationProperties); Assert.Equal(1, entityType.Members.Count); }
private void ConfigureInverse(AssociationType associationType, EdmModel model) { if (this._inverseNavigationProperty == (PropertyInfo)null) { return; } System.Data.Entity.Core.Metadata.Edm.NavigationProperty navigationProperty = model.GetNavigationProperty(this._inverseNavigationProperty); if (navigationProperty == null || navigationProperty.Association == associationType) { return; } associationType.SourceEnd.RelationshipMultiplicity = navigationProperty.Association.TargetEnd.RelationshipMultiplicity; if (associationType.Constraint == null && this._constraint == null && navigationProperty.Association.Constraint != null) { associationType.Constraint = navigationProperty.Association.Constraint; associationType.Constraint.FromRole = (RelationshipEndMember)associationType.SourceEnd; associationType.Constraint.ToRole = (RelationshipEndMember)associationType.TargetEnd; } model.RemoveAssociationType(navigationProperty.Association); navigationProperty.RelationshipType = (RelationshipType)associationType; navigationProperty.FromEndMember = (RelationshipEndMember)associationType.TargetEnd; navigationProperty.ToEndMember = (RelationshipEndMember)associationType.SourceEnd; }
private bool TryFindNavigationProperties( Type type, StructuralType cspaceType, StructuralType ospaceType, IEnumerable <PropertyInfo> clrProperties, List <Action> referenceResolutionListForCurrentType) { List <KeyValuePair <NavigationProperty, PropertyInfo> > keyValuePairList = new List <KeyValuePair <NavigationProperty, PropertyInfo> >(); foreach (NavigationProperty declaredOnlyMember in cspaceType.GetDeclaredOnlyMembers <NavigationProperty>()) { NavigationProperty cspaceProperty = declaredOnlyMember; PropertyInfo propertyInfo = clrProperties.FirstOrDefault <PropertyInfo>((Func <PropertyInfo, bool>)(p => OSpaceTypeFactory.NonPrimitiveMemberMatchesByConvention(p, (EdmMember)cspaceProperty))); if (propertyInfo != (PropertyInfo)null) { bool flag = cspaceProperty.ToEndMember.RelationshipMultiplicity != RelationshipMultiplicity.Many; if (propertyInfo.CanRead && (!flag || propertyInfo.CanWriteExtended())) { keyValuePairList.Add(new KeyValuePair <NavigationProperty, PropertyInfo>(cspaceProperty, propertyInfo)); } } else { this.LogLoadMessage(Strings.Validator_OSpace_Convention_MissingRequiredProperty((object)cspaceProperty.Name, (object)type.FullName), (EdmType)cspaceType); return(false); } } foreach (KeyValuePair <NavigationProperty, PropertyInfo> keyValuePair in keyValuePairList) { this.TrackClosure(keyValuePair.Value.PropertyType); StructuralType ct = cspaceType; StructuralType ot = ospaceType; NavigationProperty cp = keyValuePair.Key; referenceResolutionListForCurrentType.Add((Action)(() => this.CreateAndAddNavigationProperty(ct, ot, cp))); } return(true); }
public IFluentConfiguration Discover(NavigationProperty navigationProperty, DbModel model) { Debug.Assert(navigationProperty != null, "navigationProperty is null."); Debug.Assert(model != null, "model is null."); var fromEndMember = navigationProperty.FromEndMember; var toEndMember = navigationProperty.ToEndMember; if (fromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many && toEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) { // Doesn't apply return null; } var deleteBehavior = fromEndMember.RelationshipMultiplicity != RelationshipMultiplicity.Many && toEndMember.RelationshipMultiplicity != RelationshipMultiplicity.One ? fromEndMember.DeleteBehavior : toEndMember.DeleteBehavior; var defaultDeleteBehavior = (((fromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One && toEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) || (fromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many && toEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One)) && fromEndMember.GetEntityType() != toEndMember.GetEntityType()) ? OperationAction.Cascade : OperationAction.None; if (deleteBehavior == defaultDeleteBehavior) { // By convention return null; } return new CascadeDeleteConfiguration { DeleteBehavior = deleteBehavior }; }
public static void Create_sets_properties_and_seals_the_instance() { var typeUsage = TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String)); var associationType = new AssociationType("AssociationType", "Namespace", true, DataSpace.CSpace); var source = new EntityType("Source", "Namespace", DataSpace.CSpace); var target = new EntityType("Target", "Namespace", DataSpace.CSpace); var sourceEnd = new AssociationEndMember("SourceEnd", source); var targetEnd = new AssociationEndMember("TargetEnd", target); var navigationProperty = NavigationProperty.Create( "NavigationProperty", typeUsage, associationType, sourceEnd, targetEnd, new[] { new MetadataProperty( "TestProperty", TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String)), "value"), }); Assert.Equal("NavigationProperty", navigationProperty.Name); Assert.Same(typeUsage, navigationProperty.TypeUsage); Assert.Same(associationType, navigationProperty.RelationshipType); Assert.Same(sourceEnd, navigationProperty.FromEndMember); Assert.Same(targetEnd, navigationProperty.ToEndMember); Assert.True(navigationProperty.IsReadOnly); var metadataProperty = navigationProperty.MetadataProperties.SingleOrDefault(p => p.Name == "TestProperty"); Assert.NotNull(metadataProperty); Assert.Equal("value", metadataProperty.Value); }
public static void Create_sets_properties_and_seals_the_instance() { var typeUsage = TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String)); var associationType = new AssociationType("AssociationType", "Namespace", true, DataSpace.CSpace); var source = new EntityType("Source", "Namespace", DataSpace.CSpace); var target = new EntityType("Target", "Namespace", DataSpace.CSpace); var sourceEnd = new AssociationEndMember("SourceEnd", source); var targetEnd = new AssociationEndMember("TargetEnd", target); var navigationProperty = NavigationProperty.Create( "NavigationProperty", typeUsage, associationType, sourceEnd, targetEnd); Assert.Equal("NavigationProperty", navigationProperty.Name); Assert.Same(typeUsage, navigationProperty.TypeUsage); Assert.Same(associationType, navigationProperty.RelationshipType); Assert.Same(sourceEnd, navigationProperty.FromEndMember); Assert.Same(targetEnd, navigationProperty.ToEndMember); Assert.True(navigationProperty.IsReadOnly); }
/// <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; }
public void AddNavigationProperty(NavigationProperty property) { AddMember(property, true); }
/// <summary> /// Creates a NavigationProperty instance from the specified parameters. /// </summary> /// <param name="name">The name of the navigation property.</param> /// <param name="typeUsage">Specifies the navigation property type and its facets.</param> /// <param name="relationshipType">The relationship type for the navigation.</param> /// <param name="from">The source end member in the navigation.</param> /// <param name="to">The target end member in the navigation.</param> /// <param name="metadataProperties">The metadata properties of the navigation property.</param> /// <returns>The newly created NavigationProperty instance.</returns> public static NavigationProperty Create( string name, TypeUsage typeUsage, RelationshipType relationshipType, RelationshipEndMember from, RelationshipEndMember to, IEnumerable<MetadataProperty> metadataProperties) { Check.NotEmpty(name, "name"); Check.NotNull(typeUsage, "typeUsage"); var instance = new NavigationProperty(name, typeUsage); instance.RelationshipType = relationshipType; instance.FromEndMember = from; instance.ToEndMember = to; if (metadataProperties != null) { instance.AddMetadataProperties(metadataProperties.ToList()); } instance.SetReadOnly(); return instance; }
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(); }
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 void ResolveNavigationProperty(StructuralType declaringType, PropertyInfo propertyInfo) { // 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. var relationshipPropertyAttributes = propertyInfo.GetCustomAttributes <EdmRelationshipNavigationPropertyAttribute>(inherit: false); Debug.Assert(relationshipPropertyAttributes.Count() == 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( Strings.Validator_OSpace_InvalidNavPropReturnType( propertyInfo.Name, propertyInfo.DeclaringType.FullName, propertyInfo.PropertyType.FullName))); 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 var attribute = (EdmRelationshipNavigationPropertyAttribute)relationshipPropertyAttributes.First(); EdmMember member = null; EdmType type; if (SessionData.TypesInLoading.TryGetValue(attribute.RelationshipNamespaceName + "." + attribute.RelationshipName, out type) && Helper.IsAssociationType(type)) { var relationshipType = (AssociationType)type; if (relationshipType != null) { // The return value of this property has been verified, so create the property now var navigationProperty = new NavigationProperty(propertyInfo.Name, TypeUsage.Create(propertyType)); 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( Strings.TargetRoleNameInNavigationPropertyNotValid( propertyInfo.Name, propertyInfo.DeclaringType.FullName, attribute.TargetRoleName, attribute.RelationshipName))); member = null; } if (member != null && ((RefType)navigationProperty.FromEndMember.TypeUsage.EdmType).ElementType.ClrType != declaringType.ClrType) { SessionData.EdmItemErrors.Add( new EdmItemError( Strings.NavigationPropertyRelationshipEndTypeMismatch( declaringType.FullName, navigationProperty.Name, relationshipType.FullName, navigationProperty.FromEndMember.Name, ((RefType)navigationProperty.FromEndMember.TypeUsage.EdmType).ElementType.ClrType))); member = null; } } } else { SessionData.EdmItemErrors.Add( new EdmItemError( Strings.RelationshipNameInNavigationPropertyNotValid( propertyInfo.Name, propertyInfo.DeclaringType.FullName, attribute.RelationshipName))); } if (member != null) { declaringType.AddMember(member); } }
protected override void VisitEdmNavigationProperty(NavigationProperty item) { _schemaWriter.WriteNavigationPropertyElementHeader(item); base.VisitEdmNavigationProperty(item); _schemaWriter.WriteEndElement(); }
public void AddNavigationProperty(NavigationProperty property) { Check.NotNull(property, "property"); AddMember(property, true); }
private void CreateAndAddNavigationProperty( StructuralType cspaceType, StructuralType ospaceType, NavigationProperty cspaceProperty) { EdmType ospaceRelationship; if (CspaceToOspace.TryGetValue(cspaceProperty.RelationshipType, out ospaceRelationship)) { Debug.Assert(ospaceRelationship is StructuralType, "Structural type expected."); var foundTarget = false; EdmType targetType = null; if (Helper.IsCollectionType(cspaceProperty.TypeUsage.EdmType)) { EdmType findType; foundTarget = CspaceToOspace.TryGetValue( ((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 = CspaceToOspace.TryGetValue(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"); var navigationProperty = new NavigationProperty(cspaceProperty.Name, TypeUsage.Create(targetType)); var relationshipType = (RelationshipType)ospaceRelationship; navigationProperty.RelationshipType = relationshipType; // we can use First because o-space relationships are created directly from // c-space relationship navigationProperty.ToEndMember = (RelationshipEndMember)relationshipType.Members.First(e => e.Name == cspaceProperty.ToEndMember.Name); navigationProperty.FromEndMember = (RelationshipEndMember)relationshipType.Members.First(e => e.Name == cspaceProperty.FromEndMember.Name); ospaceType.AddMember(navigationProperty); } else { var missingType = cspaceProperty.RelationshipType.RelationshipEndMembers.Select(e => ((RefType)e.TypeUsage.EdmType).ElementType).First( e => e != cspaceType); LogError( Strings.Validator_OSpace_Convention_RelationshipNotLoaded( cspaceProperty.RelationshipType.FullName, missingType.FullName), missingType); } }
/// <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) { }
protected virtual void Visit(NavigationProperty navigationProperty) { Visit(navigationProperty.FromEndMember); Visit(navigationProperty.RelationshipType); Visit(navigationProperty.ToEndMember); Visit(navigationProperty.TypeUsage); }
public void AddNavigationProperty(NavigationProperty property) { Check.NotNull <NavigationProperty>(property, nameof(property)); this.AddMember((EdmMember)property, true); }
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); }
internal void Configure( NavigationProperty navigationProperty, EdmModel model, EntityTypeConfiguration entityTypeConfiguration) { DebugCheck.NotNull(navigationProperty); DebugCheck.NotNull(model); DebugCheck.NotNull(entityTypeConfiguration); navigationProperty.SetConfiguration(this); var associationType = navigationProperty.Association; var configuration = associationType.GetConfiguration() as NavigationPropertyConfiguration; if (configuration == null) { associationType.SetConfiguration(this); } else { ValidateConsistency(configuration); } ConfigureInverse(associationType, model); ConfigureEndKinds(associationType, configuration); ConfigureDependentBehavior(associationType, model, entityTypeConfiguration); }
/// <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) { var relationship = 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]; }
/// <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); }
private static string GetForeignKey(NavigationProperty navigationProperty) { var association = navigationProperty.RelationshipType as AssociationType; if (association == null) return null; // only support first constraint var referentialConstraint = association.ReferentialConstraints.FirstOrDefault(); if (referentialConstraint == null) return null; var toProperties = referentialConstraint .ToProperties .Select(p => p.Name) .ToArray(); return string.Join(",", toProperties); }
private static object GetDisplayValue(AuditEntryState state, NavigationProperty navigationProperty, IMemberAccessor displayMember, DbDataRecord values) { if (values == null) return null; var association = navigationProperty.RelationshipType as AssociationType; if (association == null) return null; // only support first constraint var referentialConstraint = association.ReferentialConstraints.FirstOrDefault(); if (referentialConstraint == null) return null; var toProperties = referentialConstraint .ToProperties .Select(p => p.Name) .ToList(); var fromProperties = referentialConstraint .FromProperties .Select(p => p.Name) .ToList(); // make sure key columns match if (fromProperties.Count != toProperties.Count) return null; var edmType = referentialConstraint .FromProperties .Select(p => p.DeclaringType) .FirstOrDefault(); if (edmType == null) return null; var entitySet = state.ObjectContext.GetEntitySet(edmType.FullName); var sql = new StringBuilder(); sql.Append("SELECT VALUE t.") .Append(displayMember.Name) .Append(" FROM ") .Append(entitySet.Name) .Append(" as t") .Append(" WHERE "); var parameters = new List<ObjectParameter>(); for (int index = 0; index < fromProperties.Count; index++) { if (index > 0) sql.Append(" AND "); string fromProperty = fromProperties[index]; string toProperty = toProperties[index]; var value = values.GetValue(toProperty); var name = "@" + fromProperty; sql.Append(" t.").Append(fromProperty); if (value != null) { sql.Append(" == ").Append(name); parameters.Add(new ObjectParameter(fromProperty, value)); } else { sql.Append(" is null"); } } var q = state.ObjectContext.CreateQuery<object>( sql.ToString(), parameters.ToArray()); return q.FirstOrDefault(); }
public void TranslateColumnMap_returns_correct_columntypes_and_nullablecolumns_for_associations() { var metadataWorkspaceMock = new Mock<MetadataWorkspace>(); metadataWorkspaceMock.Setup(m => m.GetQueryCacheManager()).Returns(QueryCacheManager.Create()); var codeFirstOSpaceTypeFactory = new CodeFirstOSpaceTypeFactory(); var refEntityColumnMap = (EntityColumnMap)BuildSimpleEntitySetColumnMap(metadataWorkspaceMock, codeFirstOSpaceTypeFactory).Element; var cSpaceEntityType = new EntityType(typeof(RefEntity).Name, "N", DataSpace.CSpace); cSpaceEntityType.AddMember(new EdmProperty("Id", TypeUsage.Create(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)))); var navigationProperty = new NavigationProperty("SimpleEntity", TypeUsage.Create(refEntityColumnMap.Type.EdmType)); var associationType = new AssociationType("A", "N", false, DataSpace.CSpace); associationType.AddMember( new AssociationEndMember("From", new RefType(cSpaceEntityType), RelationshipMultiplicity.One)); associationType.AddMember( new AssociationEndMember("To", new RefType((EntityType)navigationProperty.TypeUsage.EdmType), RelationshipMultiplicity.One)); associationType.SetReadOnly(); navigationProperty.RelationshipType = associationType; navigationProperty.FromEndMember = associationType.RelationshipEndMembers[0]; navigationProperty.ToEndMember = associationType.RelationshipEndMembers[1]; cSpaceEntityType.AddMember(navigationProperty); var entityTypeUsage = TypeUsage.Create(cSpaceEntityType); var oSpaceEntityType = codeFirstOSpaceTypeFactory.TryCreateType(typeof(RefEntity), cSpaceEntityType); codeFirstOSpaceTypeFactory.CspaceToOspace.Add(cSpaceEntityType, oSpaceEntityType); var associations = new EdmItemCollection(); associations.AddInternal(associationType); codeFirstOSpaceTypeFactory.CreateRelationships(associations); foreach (var resolve in codeFirstOSpaceTypeFactory.ReferenceResolutions) { resolve(); } var idScalarMap = new ScalarColumnMap(TypeUsage.Create(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)), "Id", 0, 1); var refColumnMap = new RefColumnMap( associationType.RelationshipEndMembers[1].TypeUsage, "E", new SimpleEntityIdentity(null, new SimpleColumnMap[] { idScalarMap })); var collectionMap = new SimpleCollectionColumnMap( entityTypeUsage, "MockCollectionType", refColumnMap, null, null); metadataWorkspaceMock.Setup(m => m.GetItem<EdmType>("N.RefEntity", DataSpace.OSpace)) .Returns(oSpaceEntityType); var factory = new Translator().TranslateColumnMap<object>( collectionMap, metadataWorkspaceMock.Object, new SpanIndex(), MergeOption.NoTracking, streaming: false, valueLayer: false); Assert.NotNull(factory); Assert.Equal(new[] { null, typeof(int) }, factory.ColumnTypes); Assert.Equal(new[] { false, true }, factory.NullableColumns); }
protected override void VisitEdmNavigationProperty(NavigationProperty item) { this._schemaWriter.WriteNavigationPropertyElementHeader(item); base.VisitEdmNavigationProperty(item); this._schemaWriter.WriteEndElement(); }