private void RediscoverComplexTypes(IEnumerable <IStructuralTypeConfiguration> explicitlyAddedTypes) { IEnumerable <IEntityTypeConfiguration> misconfiguredEntityTypes = StructuralTypes .Except(explicitlyAddedTypes) .OfType <IEntityTypeConfiguration>() .Where(entity => !entity.Keys.Any()) .ToArray(); IEnumerable <IEntityTypeConfiguration> actualEntityTypes = StructuralTypes .Except(misconfiguredEntityTypes) .OfType <IEntityTypeConfiguration>() .ToArray(); foreach (IEntityTypeConfiguration misconfiguredEntityType in misconfiguredEntityTypes) { RemoveStructuralType(misconfiguredEntityType.ClrType); foreach (IEntityTypeConfiguration entityToBePatched in actualEntityTypes) { NavigationPropertyConfiguration[] propertiesToBeRemoved = entityToBePatched .NavigationProperties .Where(navigationProperty => navigationProperty.RelatedClrType == misconfiguredEntityType.ClrType) .ToArray(); foreach (NavigationPropertyConfiguration propertyToBeRemoved in propertiesToBeRemoved) { entityToBePatched.RemoveProperty(propertyToBeRemoved.PropertyInfo); entityToBePatched.AddComplexProperty(propertyToBeRemoved.PropertyInfo); } } AddComplexType(misconfiguredEntityType.ClrType); } }
// patch up the base type for all entities that don't have any yet. internal void DiscoverInheritanceRelationships() { Dictionary <Type, EntityTypeConfiguration> entityMap = StructuralTypes.OfType <EntityTypeConfiguration>().ToDictionary(e => e.ClrType); foreach (EntityTypeConfiguration entity in StructuralTypes.OfType <EntityTypeConfiguration>().Where(e => !e.BaseTypeConfigured)) { Type baseClrType = entity.ClrType.BaseType; while (baseClrType != null) { // see if we there is an entity that we know mapping to this clr types base type. EntityTypeConfiguration baseEntityType; if (entityMap.TryGetValue(baseClrType, out baseEntityType)) { RemoveBaseTypeProperties(entity, baseEntityType); // disable derived type key check if we are building a model for query composition. if (_isQueryCompositionMode) { // modifying the collection in the iterator, hence the ToArray(). foreach (PrimitivePropertyConfiguration keyProperty in entity.Keys.ToArray()) { entity.RemoveKey(keyProperty); } } entity.DerivesFrom(baseEntityType); break; } baseClrType = baseClrType.BaseType; } } }
private IEdmTypeConfiguration GetStructuralTypeOrNull(Type clrType) { IEdmTypeConfiguration configuration = StructuralTypes.SingleOrDefault(edmType => edmType.ClrType == clrType); if (configuration == null) { Type type = TypeHelper.GetUnderlyingTypeOrSelf(clrType); configuration = EnumTypes.SingleOrDefault(edmType => edmType.ClrType == type); } return(configuration); }
private void RediscoverComplexTypes() { Contract.Assert(_explicitlyAddedTypes != null); EntityTypeConfiguration[] misconfiguredEntityTypes = StructuralTypes .Except(_explicitlyAddedTypes) .OfType <EntityTypeConfiguration>() .Where(entity => !entity.Keys().Any()) .ToArray(); ReconfigureEntityTypesAsComplexType(misconfiguredEntityTypes); }
public override IEdmModel GetEdmModel() { if (_isModelBeingBuilt) { throw Error.NotSupported(SRResources.GetEdmModelCalledMoreThanOnce); } // before we begin, get the set of types the user had added explicitly. _explicitlyAddedTypes = new List <IStructuralTypeConfiguration>(StructuralTypes); _isModelBeingBuilt = true; MapTypes(); _conventionsBeingApplied = true; // Apply type conventions. Note the call to ToArray() is required as the StructuralTypes collection // could get modified during ApplyTypeConventions(). foreach (IStructuralTypeConfiguration edmTypeConfiguration in StructuralTypes.ToArray()) { ApplyTypeConventions(edmTypeConfiguration); } // Apply property conventions. Note the call to ToArray() is required as the StructuralTypes collection // could get modified during ApplyPropertyConventions(). Also, type conventions might have // modified this. So, call ToArray() again. foreach (IStructuralTypeConfiguration edmTypeConfiguration in StructuralTypes.ToArray()) { ApplyPropertyConventions(edmTypeConfiguration); } // Don't RediscoverComplexTypes() and treat everything as an entity type if buidling a model for QueryableAttribute. if (!_isQueryCompositionMode) { RediscoverComplexTypes(); } // prune unreachable types PruneUnreachableTypes(); // Apply entity set conventions. IEnumerable <IEntitySetConfiguration> explictlyConfiguredEntitySets = new List <IEntitySetConfiguration>(EntitySets); foreach (IEntitySetConfiguration entitySet in explictlyConfiguredEntitySets) { ApplyEntitySetConventions(entitySet); } return(base.GetEdmModel()); }
private void ReconfigureEntityTypesAsComplexType(EntityTypeConfiguration[] misconfiguredEntityTypes) { IEnumerable <EntityTypeConfiguration> actualEntityTypes = StructuralTypes .Except(misconfiguredEntityTypes) .OfType <EntityTypeConfiguration>(); foreach (EntityTypeConfiguration misconfiguredEntityType in misconfiguredEntityTypes) { RemoveStructuralType(misconfiguredEntityType.ClrType); // this is a wrongly inferred type. so just ignore any pending configuration from it. AddComplexType(misconfiguredEntityType.ClrType); foreach (EntityTypeConfiguration entityToBePatched in actualEntityTypes) { NavigationPropertyConfiguration[] propertiesToBeRemoved = entityToBePatched .NavigationProperties .Where(navigationProperty => navigationProperty.RelatedClrType == misconfiguredEntityType.ClrType) .ToArray(); foreach (NavigationPropertyConfiguration propertyToBeRemoved in propertiesToBeRemoved) { string propertyNameAlias = propertyToBeRemoved.Name; PropertyConfiguration propertyConfiguration; entityToBePatched.RemoveProperty(propertyToBeRemoved.PropertyInfo); if (propertyToBeRemoved.Multiplicity == EdmMultiplicity.Many) { propertyConfiguration = entityToBePatched.AddCollectionProperty(propertyToBeRemoved.PropertyInfo); } else { propertyConfiguration = entityToBePatched.AddComplexProperty(propertyToBeRemoved.PropertyInfo); } Contract.Assert(propertyToBeRemoved.AddedExplicitly == false); // The newly added property must be marked as added implicitly. This can make sure the property // conventions can be re-applied to the new property. propertyConfiguration.AddedExplicitly = false; ReapplyPropertyConvention(propertyConfiguration, entityToBePatched); propertyConfiguration.Name = propertyNameAlias; } } } }
// the convention model builder MapTypes() method might have went through deep object graphs and added a bunch of types // only to realise after applying the conventions that the user has ignored some of the properties. So, prune the unreachable stuff. private void PruneUnreachableTypes() { Contract.Assert(_explicitlyAddedTypes != null); // Do a BFS starting with the types the user has explicitly added to find out the unreachable nodes. Queue <IStructuralTypeConfiguration> reachableTypes = new Queue <IStructuralTypeConfiguration>(_explicitlyAddedTypes); HashSet <IStructuralTypeConfiguration> visitedTypes = new HashSet <IStructuralTypeConfiguration>(); while (reachableTypes.Count != 0) { IStructuralTypeConfiguration currentType = reachableTypes.Dequeue(); // go visit other end of each of this node's edges. foreach (PropertyConfiguration property in currentType.Properties.Where(property => property.Kind != PropertyKind.Primitive)) { if (property.Kind == PropertyKind.Collection) { // if the elementType is primitive we don't need to do anything. CollectionPropertyConfiguration colProperty = property as CollectionPropertyConfiguration; if (EdmLibHelpers.GetEdmPrimitiveTypeOrNull(colProperty.ElementType) != null) { continue; } } IStructuralTypeConfiguration propertyType = GetStructuralTypeOrNull(property.RelatedClrType); Contract.Assert(propertyType != null, "we should already have seen this type"); if (!visitedTypes.Contains(propertyType)) { reachableTypes.Enqueue(propertyType); } } visitedTypes.Add(currentType); } IStructuralTypeConfiguration[] allConfiguredTypes = StructuralTypes.ToArray(); foreach (IStructuralTypeConfiguration type in allConfiguredTypes) { if (!visitedTypes.Contains(type)) { // we don't have to fix up any properties because this type is unreachable and cannot be a property of any reachable type. RemoveStructuralType(type.ClrType); } } }
private void ApplyForeignKeyConventions() { ForeignKeyAttributeConvention foreignKeyAttributeConvention = new ForeignKeyAttributeConvention(); ForeignKeyDiscoveryConvention foreignKeyDiscoveryConvention = new ForeignKeyDiscoveryConvention(); ActionOnDeleteAttributeConvention actionOnDeleteConvention = new ActionOnDeleteAttributeConvention(); foreach (EntityTypeConfiguration edmType in StructuralTypes.OfType <EntityTypeConfiguration>()) { foreach (PropertyConfiguration property in edmType.Properties) { // ForeignKeyDiscoveryConvention has to run after ForeignKeyAttributeConvention foreignKeyAttributeConvention.Apply(property, edmType, this); foreignKeyDiscoveryConvention.Apply(property, edmType, this); actionOnDeleteConvention.Apply(property, edmType, this); } } }
internal void ReconfigInferedEntityTypeAsComplexType(Type propertyType) { HashSet <Type> visitedTypes = new HashSet <Type>(); Queue <Type> typeToBeVisited = new Queue <Type>(); typeToBeVisited.Enqueue(propertyType); IList <EntityTypeConfiguration> foundMappedTypes = new List <EntityTypeConfiguration>(); while (typeToBeVisited.Count != 0) { Type currentType = typeToBeVisited.Dequeue(); visitedTypes.Add(currentType); List <Type> derivedTypes; if (_allTypesWithDerivedTypeMapping.Value.TryGetValue(currentType, out derivedTypes)) { foreach (Type derivedType in derivedTypes) { if (!visitedTypes.Contains(derivedType)) { StructuralTypeConfiguration structuralType = StructuralTypes.Except(_explicitlyAddedTypes) .FirstOrDefault(c => c.ClrType == derivedType); if (structuralType != null && structuralType.Kind == EdmTypeKind.Entity) { foundMappedTypes.Add((EntityTypeConfiguration)structuralType); } typeToBeVisited.Enqueue(derivedType); } } } } if (foundMappedTypes.Any()) { ReconfigureEntityTypesAsComplexType(foundMappedTypes.ToArray()); } }
private void ReconfigureEntityTypesAsComplexType(EntityTypeConfiguration[] misconfiguredEntityTypes) { IEnumerable <EntityTypeConfiguration> actualEntityTypes = StructuralTypes .Except(misconfiguredEntityTypes) .OfType <EntityTypeConfiguration>(); foreach (EntityTypeConfiguration misconfiguredEntityType in misconfiguredEntityTypes) { RemoveStructuralType(misconfiguredEntityType.ClrType); // this is a wrongly inferred type. so just ignore any pending configuration from it. AddComplexType(misconfiguredEntityType.ClrType); foreach (EntityTypeConfiguration entityToBePatched in actualEntityTypes) { NavigationPropertyConfiguration[] propertiesToBeRemoved = entityToBePatched .NavigationProperties .Where(navigationProperty => navigationProperty.RelatedClrType == misconfiguredEntityType.ClrType) .ToArray(); foreach (NavigationPropertyConfiguration propertyToBeRemoved in propertiesToBeRemoved) { string propertyNameAlias = propertyToBeRemoved.Name; PropertyConfiguration propertyConfiguration; entityToBePatched.RemoveProperty(propertyToBeRemoved.PropertyInfo); if (propertyToBeRemoved.Multiplicity == EdmMultiplicity.Many) { propertyConfiguration = entityToBePatched.AddCollectionProperty(propertyToBeRemoved.PropertyInfo); } else { propertyConfiguration = entityToBePatched.AddComplexProperty(propertyToBeRemoved.PropertyInfo); } propertyConfiguration.Name = propertyNameAlias; } } } }
private void ReconfigureEntityTypesAsComplexType(IEnumerable <EntityTypeConfiguration> misconfiguredEntityTypes) { IEnumerable <EntityTypeConfiguration> actualEntityTypes = StructuralTypes .Except(misconfiguredEntityTypes) .OfType <EntityTypeConfiguration>() .ToArray(); foreach (EntityTypeConfiguration misconfiguredEntityType in misconfiguredEntityTypes) { RemoveStructuralType(misconfiguredEntityType.ClrType); ComplexTypeConfiguration newComplexType = AddComplexType(misconfiguredEntityType.ClrType); foreach (PropertyInfo ignoredProperty in misconfiguredEntityType.IgnoredProperties) { newComplexType.RemoveProperty(ignoredProperty); } foreach (EntityTypeConfiguration entityToBePatched in actualEntityTypes) { NavigationPropertyConfiguration[] propertiesToBeRemoved = entityToBePatched .NavigationProperties .Where(navigationProperty => navigationProperty.RelatedClrType == misconfiguredEntityType.ClrType) .ToArray(); foreach (NavigationPropertyConfiguration propertyToBeRemoved in propertiesToBeRemoved) { entityToBePatched.RemoveProperty(propertyToBeRemoved.PropertyInfo); if (propertyToBeRemoved.Multiplicity == EdmMultiplicity.Many) { entityToBePatched.AddCollectionProperty(propertyToBeRemoved.PropertyInfo); } else { entityToBePatched.AddComplexProperty(propertyToBeRemoved.PropertyInfo); } } } } }
// patch up the base type for all entities that don't have any yet. internal void DiscoverInheritanceRelationships() { Dictionary <Type, EntityTypeConfiguration> entityMap = StructuralTypes.OfType <EntityTypeConfiguration>().ToDictionary(e => e.ClrType); foreach (EntityTypeConfiguration entity in StructuralTypes.OfType <EntityTypeConfiguration>().Where(e => !e.BaseTypeConfigured).ToArray()) { Type baseClrType = entity.ClrType.BaseType; while (baseClrType != null) { // see if we there is an entity that we know mapping to this clr types base type. EntityTypeConfiguration baseEntityType; if (entityMap.TryGetValue(baseClrType, out baseEntityType)) { RemoveBaseTypeProperties(entity, baseEntityType); entity.DerivesFrom(baseEntityType); break; } baseClrType = baseClrType.BaseType; } } }
private void ReconfigureEntityTypesAsComplexType(IEnumerable <IEntityTypeConfiguration> misconfiguredEntityTypes) { IEnumerable <IEntityTypeConfiguration> actualEntityTypes = StructuralTypes .Except(misconfiguredEntityTypes) .OfType <IEntityTypeConfiguration>() .ToArray(); foreach (IEntityTypeConfiguration misconfiguredEntityType in misconfiguredEntityTypes) { RemoveStructuralType(misconfiguredEntityType.ClrType); IComplexTypeConfiguration newComplexType = AddComplexType(misconfiguredEntityType.ClrType); foreach (var ignoredProperty in misconfiguredEntityType.IgnoredProperties) { newComplexType.RemoveProperty(ignoredProperty); } foreach (IEntityTypeConfiguration entityToBePatched in actualEntityTypes) { NavigationPropertyConfiguration[] propertiesToBeRemoved = entityToBePatched .NavigationProperties .Where(navigationProperty => navigationProperty.RelatedClrType == misconfiguredEntityType.ClrType) .ToArray(); foreach (NavigationPropertyConfiguration propertyToBeRemoved in propertiesToBeRemoved) { if (propertyToBeRemoved.Multiplicity == EdmMultiplicity.Many) { // complex collections are not supported. throw Error.NotSupported(SRResources.CollectionPropertiesNotSupported, propertyToBeRemoved.PropertyInfo.Name, propertyToBeRemoved.PropertyInfo.ReflectedType.FullName); } entityToBePatched.RemoveProperty(propertyToBeRemoved.PropertyInfo); entityToBePatched.AddComplexProperty(propertyToBeRemoved.PropertyInfo); } } AddComplexType(misconfiguredEntityType.ClrType); } }
private void ReconfigureEntityTypesAsComplexType(EntityTypeConfiguration[] misconfiguredEntityTypes) { IList <EntityTypeConfiguration> actualEntityTypes = StructuralTypes.OfType <EntityTypeConfiguration>() .Where(entity => entity.Keys().Any()) .Concat(_explicitlyAddedTypes.OfType <EntityTypeConfiguration>()) .Except(misconfiguredEntityTypes) .ToList(); HashSet <EntityTypeConfiguration> visitedEntityType = new HashSet <EntityTypeConfiguration>(); foreach (EntityTypeConfiguration misconfiguredEntityType in misconfiguredEntityTypes) { if (visitedEntityType.Contains(misconfiguredEntityType)) { continue; } // If one of the base types is already configured as entity type, we should keep this type as entity type. IEnumerable <EntityTypeConfiguration> basedTypes = misconfiguredEntityType .BaseTypes().OfType <EntityTypeConfiguration>(); if (actualEntityTypes.Any(e => basedTypes.Any(a => a.ClrType == e.ClrType))) { visitedEntityType.Add(misconfiguredEntityType); continue; } // Make sure to remove current type and all the derived types IList <EntityTypeConfiguration> thisAndDerivedTypes = this.DerivedTypes(misconfiguredEntityType) .Concat(new[] { misconfiguredEntityType }).OfType <EntityTypeConfiguration>().ToList(); foreach (EntityTypeConfiguration subEnityType in thisAndDerivedTypes) { if (actualEntityTypes.Any(e => e.ClrType == subEnityType.ClrType)) { throw Error.InvalidOperation(SRResources.CannotReconfigEntityTypeAsComplexType, misconfiguredEntityType.ClrType.FullName, subEnityType.ClrType.FullName); } RemoveStructuralType(subEnityType.ClrType); } // this is a wrongly inferred type. so just ignore any pending configuration from it. AddComplexType(misconfiguredEntityType.ClrType); foreach (EntityTypeConfiguration subEnityType in thisAndDerivedTypes) { visitedEntityType.Add(subEnityType); // go through all structural types to remove all properties defined by this mis-configed type. IList <StructuralTypeConfiguration> allTypes = StructuralTypes.ToList(); foreach (StructuralTypeConfiguration structuralToBePatched in allTypes) { NavigationPropertyConfiguration[] propertiesToBeRemoved = structuralToBePatched .NavigationProperties .Where(navigationProperty => navigationProperty.RelatedClrType == subEnityType.ClrType) .ToArray(); foreach (NavigationPropertyConfiguration propertyToBeRemoved in propertiesToBeRemoved) { string propertyNameAlias = propertyToBeRemoved.Name; PropertyConfiguration propertyConfiguration; structuralToBePatched.RemoveProperty(propertyToBeRemoved.PropertyInfo); if (propertyToBeRemoved.Multiplicity == EdmMultiplicity.Many) { propertyConfiguration = structuralToBePatched.AddCollectionProperty(propertyToBeRemoved.PropertyInfo); } else { propertyConfiguration = structuralToBePatched.AddComplexProperty(propertyToBeRemoved.PropertyInfo); } Contract.Assert(propertyToBeRemoved.AddedExplicitly == false); // The newly added property must be marked as added implicitly. This can make sure the property // conventions can be re-applied to the new property. propertyConfiguration.AddedExplicitly = false; ReapplyPropertyConvention(propertyConfiguration, structuralToBePatched); propertyConfiguration.Name = propertyNameAlias; } } } } }
private IStructuralTypeConfiguration GetStructuralTypeOrNull(Type clrType) { return(StructuralTypes.Where(edmType => edmType.ClrType == clrType).SingleOrDefault()); }