private static bool RemapsInheritedProperties( DbDatabaseMapping databaseMapping, DbEntityTypeMapping entityTypeMapping) { var inheritedProperties = entityTypeMapping.EntityType.Properties .Except(entityTypeMapping.EntityType.DeclaredProperties) .Except(entityTypeMapping.EntityType.GetKeyProperties()); foreach (var property in inheritedProperties) { var fragment = GetFragmentForPropertyMapping(entityTypeMapping, property); if (fragment != null) { // find if this inherited property is mapped to another table by a base type var baseType = entityTypeMapping.EntityType.BaseType; while (baseType != null) { if (databaseMapping.GetEntityTypeMappings(baseType) .Select(baseTypeMapping => GetFragmentForPropertyMapping(baseTypeMapping, property)) .Any( baseFragment => baseFragment != null && baseFragment.Table != fragment.Table)) { return true; } baseType = baseType.BaseType; } } } return false; }
public void Configure_should_update_table_name_when_base_type_is_null() { var entityMappingConfiguration = new EntityMappingConfiguration { TableName = new DatabaseName("Foo") }; var entityTypeMapping = new DbEntityTypeMapping { EntityType = new EdmEntityType() }; var table = new DbTableMetadata { Name = "foo" }; entityTypeMapping.TypeMappingFragments.Add( new DbEntityTypeMappingFragment { Table = table }); var databaseMapping = new DbDatabaseMapping().Initialize(new EdmModel().Initialize(), new DbDatabaseMetadata().Initialize()); databaseMapping.Database.AddTable("foo"); entityMappingConfiguration.Configure( databaseMapping, ProviderRegistry.Sql2008_ProviderManifest, entityTypeMapping.EntityType, ref entityTypeMapping, false, 0, 1); Assert.Equal("Foo", table.GetTableName().Name); }
public static DbEntityTypeMapping Clone(this DbEntityTypeMapping entityTypeMappping) { //Contract.Requires(entityTypeMappping != null); var clone = new DbEntityTypeMapping { EntityType = entityTypeMappping.EntityType }; entityTypeMappping.Annotations.Copy(clone.Annotations); return clone; }
public void GetPropertyMapping_should_return_mapping_with_path() { var entityTypeMapping = new DbEntityTypeMapping(); var propertyFoo = new EdmProperty { Name = "Foo" }; var propertyBar = new EdmProperty { Name = "Bar" }; var entityPropertyMapping = new DbEdmPropertyMapping { PropertyPath = new[] { propertyFoo, propertyBar, } }; var entityTypeMappingFragment = new DbEntityTypeMappingFragment(); entityTypeMappingFragment.PropertyMappings.Add(entityPropertyMapping); entityTypeMapping.TypeMappingFragments.Add(entityTypeMappingFragment); Assert.Same(entityPropertyMapping, entityTypeMapping.GetPropertyMapping(propertyFoo, propertyBar)); }
public void Generate(EdmEntityType entityType, DbDatabaseMapping databaseMapping) { //Contract.Requires(entityType != null); //Contract.Requires(databaseMapping != null); var entitySet = databaseMapping.Model.GetEntitySet(entityType); var entitySetMapping = databaseMapping.GetEntitySetMapping(entitySet) ?? databaseMapping.AddEntitySetMapping(entitySet); var table = entitySetMapping.EntityTypeMappings.Any() ? entitySetMapping.EntityTypeMappings.First().TypeMappingFragments.First().Table : databaseMapping.Database.AddTable(entityType.GetRootType().Name); var entityTypeMappingFragment = new DbEntityTypeMappingFragment { Table = table }; var entityTypeMapping = new DbEntityTypeMapping { EntityType = entityType, IsHierarchyMapping = false }; entityTypeMapping.TypeMappingFragments.Add(entityTypeMappingFragment); entityTypeMapping.SetClrType(entityType.GetClrType()); entitySetMapping.EntityTypeMappings.Add(entityTypeMapping); new PropertyMappingGenerator(_providerManifest) .Generate( entityType, entityType.Properties, entitySetMapping, entityTypeMappingFragment, new List<EdmProperty>(), false); }
public void GetComplexPropertyMappings_should_return_all_complex_property_mappings_for_type() { var databaseMapping = new DbDatabaseMapping() .Initialize(new EdmModel().Initialize(), new DbDatabaseMetadata()); var entitySet = new EdmEntitySet(); var entitySetMapping = databaseMapping.AddEntitySetMapping(entitySet); var entityTypeMapping = new DbEntityTypeMapping(); entitySetMapping.EntityTypeMappings.Add(entityTypeMapping); var entityTypeMappingFragment = new DbEntityTypeMappingFragment(); entityTypeMapping.TypeMappingFragments.Add(entityTypeMappingFragment); var propertyMapping1 = new DbEdmPropertyMapping(); var complexType = new EdmComplexType(); complexType.SetClrType(typeof(object)); propertyMapping1.PropertyPath.Add(new EdmProperty { PropertyType = new EdmTypeReference { EdmType = complexType } }); entityTypeMappingFragment.PropertyMappings.Add(propertyMapping1); var propertyMapping2 = new DbEdmPropertyMapping(); propertyMapping2.PropertyPath.Add(new EdmProperty { PropertyType = new EdmTypeReference() }); propertyMapping2.PropertyPath.Add(new EdmProperty { PropertyType = new EdmTypeReference { EdmType = complexType } }); entityTypeMappingFragment.PropertyMappings.Add(propertyMapping2); Assert.Equal(2, databaseMapping.GetComplexPropertyMappings(typeof(object)).Count()); }
public void GetEntityTypeMapping_should_return_mapping_for_type_by_clrType() { var databaseMapping = new DbDatabaseMapping() .Initialize(new EdmModel().Initialize(), new DbDatabaseMetadata()); var entityType = new EdmEntityType { Name = "Foo" }; entityType.SetClrType(typeof(object)); var entityTypeMapping = new DbEntityTypeMapping { EntityType = entityType }; entityTypeMapping.SetClrType(typeof(object)); databaseMapping.AddEntitySetMapping(new EdmEntitySet()).EntityTypeMappings.Add(entityTypeMapping); Assert.Same(entityTypeMapping, databaseMapping.GetEntityTypeMapping(typeof(object))); }
private void RemoveFragment( EdmEntitySet entitySet, DbEntityTypeMapping entityTypeMapping, DbEntityTypeMappingFragment fragment) { // Make the default discriminator nullable if this type isn't using it but there is a base type var defaultDiscriminator = fragment.GetDefaultDiscriminator(); if (defaultDiscriminator != null && entityTypeMapping.EntityType.BaseType != null) { var columnMapping = _tableMappings[fragment.Table].ColumnMappings.SingleOrDefault( cm => cm.Column == defaultDiscriminator); if (columnMapping != null) { var propertyMapping = columnMapping.PropertyMappings.SingleOrDefault( pm => pm.EntityType == entityTypeMapping.EntityType); if (propertyMapping != null) { columnMapping.PropertyMappings.Remove(propertyMapping); } } defaultDiscriminator.IsNullable = true; } entityTypeMapping.TypeMappingFragments.Remove(fragment); if (!entityTypeMapping.TypeMappingFragments.Any()) { _databaseMapping.GetEntitySetMapping(entitySet).EntityTypeMappings.Remove(entityTypeMapping); } }
/// <summary> /// Determines if the table and entity type need mapping, and if not, removes the existing entity type mapping /// </summary> private bool FindPropertyEntityTypeMapping( TableMapping tableMapping, EdmEntitySet entitySet, EdmEntityType entityType, bool requiresIsTypeOf, out DbEntityTypeMapping entityTypeMapping, out DbEntityTypeMappingFragment fragment) { entityTypeMapping = null; fragment = null; var mapping = (from etm in _databaseMapping.GetEntityTypeMappings(entityType) from tmf in etm.TypeMappingFragments where tmf.Table == tableMapping.Table select new { TypeMapping = etm, Fragment = tmf }).SingleOrDefault(); if (mapping != null) { entityTypeMapping = mapping.TypeMapping; fragment = mapping.Fragment; if (!requiresIsTypeOf && entityType.IsAbstract) { RemoveFragment(entitySet, mapping.TypeMapping, mapping.Fragment); return false; } return true; } else { return false; } }
private DbEntityTypeMapping FindConditionTypeMapping( EdmEntityType entityType, bool requiresSplit, DbEntityTypeMapping propertiesTypeMapping) { var conditionTypeMapping = propertiesTypeMapping; if (requiresSplit) { if (!entityType.IsAbstract) { conditionTypeMapping = propertiesTypeMapping.Clone(); conditionTypeMapping.IsHierarchyMapping = false; var parentEntitySetMapping = _databaseMapping.GetEntitySetMappings().Single( esm => esm.EntityTypeMappings.Contains(propertiesTypeMapping)); parentEntitySetMapping.EntityTypeMappings.Add(conditionTypeMapping); } propertiesTypeMapping.TypeMappingFragments.Each(tmf => tmf.ColumnConditions.Clear()); } return conditionTypeMapping; }
private static DbEntityTypeMappingFragment FindConditionTypeMappingFragment( TableMapping tableMapping, DbEntityTypeMappingFragment propertiesTypeMappingFragment, DbEntityTypeMapping conditionTypeMapping) { var conditionTypeMappingFragment = conditionTypeMapping.TypeMappingFragments.SingleOrDefault(x => x.Table == tableMapping.Table); if (conditionTypeMappingFragment == null) { conditionTypeMappingFragment = EntityMappingOperations.CreateTypeMappingFragment( conditionTypeMapping, propertiesTypeMappingFragment, tableMapping.Table); conditionTypeMappingFragment.SetIsConditionOnlyFragment(true); if (propertiesTypeMappingFragment.GetDefaultDiscriminator() != null) { conditionTypeMappingFragment.SetDefaultDiscriminator( propertiesTypeMappingFragment.GetDefaultDiscriminator()); propertiesTypeMappingFragment.RemoveDefaultDiscriminatorAnnotation(); } } return conditionTypeMappingFragment; }
public void Configure( DbDatabaseMapping databaseMapping, DbProviderManifest providerManifest, EdmEntityType entityType, ref DbEntityTypeMapping entityTypeMapping, bool isMappingAnyInheritedProperty, int configurationIndex, int configurationCount) { Contract.Requires(entityType != null); Contract.Requires(databaseMapping != null); Contract.Requires(providerManifest != null); var isIdentityTable = entityType.BaseType == null && configurationIndex == 0; var fragment = FindOrCreateTypeMappingFragment( databaseMapping, ref entityTypeMapping, configurationIndex, entityType, providerManifest); var fromTable = fragment.Table; bool isTableSharing; var toTable = FindOrCreateTargetTable( databaseMapping, fragment, entityType, fromTable, out isTableSharing); var isSharingTableWithBase = DiscoverIsSharingWithBase(databaseMapping, entityType, toTable); // Ensure all specified properties are the only ones present in this fragment and table var mappingsToContain = DiscoverAllMappingsToContain( databaseMapping, entityType, toTable, isSharingTableWithBase); // Validate that specified properties can be mapped var mappingsToMove = fragment.PropertyMappings.ToList(); foreach (var propertyPath in mappingsToContain) { var propertyMapping = fragment.PropertyMappings.SingleOrDefault( pm => pm.PropertyPath.SequenceEqual(propertyPath)); if (propertyMapping == null) { throw Error.EntityMappingConfiguration_DuplicateMappedProperty( entityType.Name, propertyPath.ToString()); } mappingsToMove.Remove(propertyMapping); } // Add table constraint if there are no inherited properties if (!isIdentityTable) { bool isSplitting; var parentTable = FindParentTable( databaseMapping, fromTable, entityTypeMapping, toTable, isMappingAnyInheritedProperty, configurationIndex, configurationCount, out isSplitting); if (parentTable != null) { DatabaseOperations.AddTypeConstraint(entityType, parentTable, toTable, isSplitting); } } // Update AssociationSetMappings (IAs) and FKs if (fromTable != toTable) { if (Properties == null) { AssociationMappingOperations.MoveAllDeclaredAssociationSetMappings( databaseMapping, entityType, fromTable, toTable, !isTableSharing); ForeignKeyPrimitiveOperations.MoveAllDeclaredForeignKeyConstraintsForPrimaryKeyColumns( entityType, fromTable, toTable); } if (isMappingAnyInheritedProperty) { // With TPC, we need to move down FK constraints, even on PKs (except type mapping constraints that are not about associations) ForeignKeyPrimitiveOperations.CopyAllForeignKeyConstraintsForPrimaryKeyColumns( databaseMapping.Database, fromTable, toTable); } } if (mappingsToMove.Any()) { DbTableMetadata extraTable = null; if (configurationIndex < configurationCount - 1) { // Move all extra properties to a single new fragment var anyPropertyMapping = mappingsToMove.First(); extraTable = FindTableForTemporaryExtraPropertyMapping( databaseMapping, entityType, fromTable, toTable, anyPropertyMapping); var extraFragment = EntityMappingOperations.CreateTypeMappingFragment( entityTypeMapping, fragment, extraTable); var requiresUpdate = extraTable != fromTable; foreach (var pm in mappingsToMove) { // move the property mapping from toFragment to extraFragment EntityMappingOperations.MovePropertyMapping( databaseMapping.Database, fragment, extraFragment, pm, requiresUpdate, true); } } else { // Move each extra property mapping to a fragment refering to the table with the base mapping DbTableMetadata unmappedTable = null; foreach (var pm in mappingsToMove) { extraTable = FindTableForExtraPropertyMapping( databaseMapping, entityType, fromTable, toTable, ref unmappedTable, pm); var extraFragment = entityTypeMapping.TypeMappingFragments.SingleOrDefault(tmf => tmf.Table == extraTable); if (extraFragment == null) { extraFragment = EntityMappingOperations.CreateTypeMappingFragment( entityTypeMapping, fragment, extraTable); extraFragment.SetIsUnmappedPropertiesFragment(true); } if (extraTable == fromTable) { // move the default discriminator along with the properties MoveDefaultDiscriminator(fragment, extraFragment); } var requiresUpdate = extraTable != fromTable; EntityMappingOperations.MovePropertyMapping( databaseMapping.Database, fragment, extraFragment, pm, requiresUpdate, true); } } } // Ensure all property mappings refer to the table in the fragment // Uniquify: true if table sharing, false otherwise // FK names should be uniquified // declared properties are moved, inherited ones are copied (duplicated) EntityMappingOperations.UpdatePropertyMappings( databaseMapping.Database, fromTable, fragment, !isTableSharing); // Configure Conditions for the fragment ConfigureDefaultDiscriminator(entityType, fragment, isSharingTableWithBase); ConfigureConditions(databaseMapping, entityType, fragment, providerManifest); // Ensure all conditions refer to columns on the table in the fragment EntityMappingOperations.UpdateConditions(databaseMapping.Database, fromTable, fragment); ForeignKeyPrimitiveOperations.UpdatePrincipalTables( databaseMapping, entityType, fromTable, toTable, isMappingAnyInheritedProperty); CleanupUnmappedArtifacts(databaseMapping, fromTable); CleanupUnmappedArtifacts(databaseMapping, toTable); toTable.SetConfiguration(this); }
private void WriteEntityTypeMappingElement(DbEntityTypeMapping entityTypeMapping) { _xmlWriter.WriteStartElement(MslConstants.Element_EntityTypeMapping); _xmlWriter.WriteAttributeString( MslConstants.Attribute_TypeName, GetEntityTypeName( _entityTypeNamespace + "." + entityTypeMapping.EntityType.Name, entityTypeMapping.IsHierarchyMapping)); foreach (var mappingFragment in entityTypeMapping.TypeMappingFragments) { WriteMappingFragmentElement(mappingFragment); } _xmlWriter.WriteEndElement(); }
private static DbTableMetadata FindParentTable( DbDatabaseMapping databaseMapping, DbTableMetadata fromTable, DbEntityTypeMapping entityTypeMapping, DbTableMetadata toTable, bool isMappingInheritedProperties, int configurationIndex, int configurationCount, out bool isSplitting) { DbTableMetadata parentTable = null; isSplitting = false; // Check for entity splitting first, since splitting on a derived type in TPT/TPC will always have fromTable != toTable if (entityTypeMapping.UsesOtherTables(toTable) || configurationCount > 1) { if (configurationIndex != 0) { // Entity Splitting case parentTable = entityTypeMapping.GetPrimaryTable(); isSplitting = true; } } if (parentTable == null && fromTable != toTable && !isMappingInheritedProperties) { // TPT case var baseType = entityTypeMapping.EntityType.BaseType; while (baseType != null && parentTable == null) { // Traverse to first anscestor with a mapping var baseMapping = databaseMapping.GetEntityTypeMappings(baseType).FirstOrDefault(); if (baseMapping != null) { parentTable = baseMapping.GetPrimaryTable(); } baseType = baseType.BaseType; } } return parentTable; }
public void GetEntityTypeMapping_should_return_mapping_for_type() { var databaseMapping = new DbDatabaseMapping() .Initialize(new EdmModel().Initialize(), new DbDatabaseMetadata()); var entityType = new EdmEntityType(); var entityTypeMapping = new DbEntityTypeMapping { EntityType = entityType }; databaseMapping.AddEntitySetMapping(new EdmEntitySet()).EntityTypeMappings.Add(entityTypeMapping); Assert.Same(entityTypeMapping, databaseMapping.GetEntityTypeMapping(entityType)); }
public static DbEntityTypeMappingFragment CreateTypeMappingFragment( DbEntityTypeMapping entityTypeMapping, DbEntityTypeMappingFragment templateFragment, DbTableMetadata table) { var fragment = new DbEntityTypeMappingFragment { Table = table }; entityTypeMapping.TypeMappingFragments.Add(fragment); // Move all PK mappings to the extra fragment foreach ( var pkPropertyMapping in templateFragment.PropertyMappings.Where(pm => pm.Column.IsPrimaryKeyColumn)) { CopyPropertyMappingToFragment(pkPropertyMapping, fragment, true); } return fragment; }
private DbEntityTypeMappingFragment FindOrCreateTypeMappingFragment( DbDatabaseMapping databaseMapping, ref DbEntityTypeMapping entityTypeMapping, int configurationIndex, EdmEntityType entityType, DbProviderManifest providerManifest) { DbEntityTypeMappingFragment fragment = null; if (entityTypeMapping == null) { Contract.Assert(entityType.IsAbstract); new EntityTypeMappingGenerator(providerManifest). Generate(entityType, databaseMapping); entityTypeMapping = databaseMapping.GetEntityTypeMapping(entityType); configurationIndex = 0; } if (configurationIndex < entityTypeMapping.TypeMappingFragments.Count) { fragment = entityTypeMapping.TypeMappingFragments[configurationIndex]; } else { if (MapInheritedProperties) { throw Error.EntityMappingConfiguration_DuplicateMapInheritedProperties(entityType.Name); } else if (Properties == null) { throw Error.EntityMappingConfiguration_DuplicateMappedProperties(entityType.Name); } else { Properties.Each( p => { if ( PropertyPathToEdmPropertyPath(p, entityType).Any( pp => !entityType.KeyProperties().Contains(pp.First()))) { throw Error.EntityMappingConfiguration_DuplicateMappedProperty( entityType.Name, p.ToString()); } }); } // Special case where they've asked for an extra table related to this type that only will include the PK columns // Uniquify: can be false, always move to a new table var templateTable = entityTypeMapping.TypeMappingFragments[0].Table; fragment = EntityMappingOperations.CreateTypeMappingFragment( entityTypeMapping, entityTypeMapping.TypeMappingFragments[0], databaseMapping.Database.AddTable(templateTable.Name, templateTable)); } return fragment; }
private static DbEntityTypeMappingFragment GetFragmentForPropertyMapping( DbEntityTypeMapping entityTypeMapping, EdmProperty property) { return entityTypeMapping.TypeMappingFragments .SingleOrDefault(tmf => tmf.PropertyMappings.Any(pm => pm.PropertyPath.Last() == property)); }
internal void ConfigureTablesAndConditions( DbEntityTypeMapping entityTypeMapping, DbDatabaseMapping databaseMapping, DbProviderManifest providerManifest) { Contract.Requires(databaseMapping != null); Contract.Requires(providerManifest != null); var entityType = (entityTypeMapping != null) ? entityTypeMapping.EntityType : databaseMapping.Model.GetEntityType(ClrType); if (_entityMappingConfigurations.Any()) { for (var i = 0; i < _entityMappingConfigurations.Count; i++) { _entityMappingConfigurations[i] .Configure( databaseMapping, providerManifest, entityType, ref entityTypeMapping, IsMappingAnyInheritedProperty(entityType), i, _entityMappingConfigurations.Count); } } else { ConfigureUnconfiguredType(databaseMapping, providerManifest, entityType); } }