public void AddEntityTypeMappingFragment( EdmEntitySet entitySet, EdmEntityType entityType, DbEntityTypeMappingFragment fragment) { Contract.Assert(fragment.Table == Table); _entityTypes.Add(entitySet, entityType); var defaultDiscriminatorColumn = fragment.GetDefaultDiscriminator(); DbColumnCondition defaultDiscriminatorCondition = null; if (defaultDiscriminatorColumn != null) { defaultDiscriminatorCondition = fragment.ColumnConditions.SingleOrDefault(cc => cc.Column == defaultDiscriminatorColumn); } foreach (var pm in fragment.PropertyMappings) { var columnMapping = FindOrCreateColumnMapping(pm.Column); columnMapping.AddMapping( entityType, pm.PropertyPath, fragment.ColumnConditions.Where(cc => cc.Column == pm.Column), defaultDiscriminatorColumn == pm.Column); } // Add any column conditions that aren't mapped to properties foreach ( var cc in fragment.ColumnConditions.Where(cc => !fragment.PropertyMappings.Any(pm => pm.Column == cc.Column))) { var columnMapping = FindOrCreateColumnMapping(cc.Column); columnMapping.AddMapping(entityType, null, new[] { cc }, defaultDiscriminatorColumn == cc.Column); } }
internal void Configure( DbDatabaseMapping databaseMapping, DbEntityTypeMappingFragment fragment, EdmEntityType entityType) { Contract.Requires(fragment != null); var edmPropertyPath = EntityMappingConfiguration.PropertyPathToEdmPropertyPath(PropertyPath, entityType); if (edmPropertyPath.Count() > 1) { throw Error.InvalidNotNullCondition(PropertyPath.ToString(), entityType.Name); } var column = fragment.PropertyMappings .Where(pm => pm.PropertyPath.SequenceEqual(edmPropertyPath.Single())) .Select(pm => pm.Column) .SingleOrDefault(); if (column == null || !fragment.Table.Columns.Contains(column)) { throw Error.InvalidNotNullCondition(PropertyPath.ToString(), entityType.Name); } if (ValueConditionConfiguration.AnyBaseTypeToTableWithoutColumnCondition( databaseMapping, entityType, fragment.Table, column)) { column.IsNullable = true; } // Make the property required var newConfiguration = new Properties.Primitive.PrimitivePropertyConfiguration { IsNullable = false, OverridableConfigurationParts = OverridableConfigurationParts.OverridableInSSpace }; newConfiguration.Configure(edmPropertyPath.Single().Last()); fragment.AddNullabilityCondition(column, isNull: false); }
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 static void UpdateConditions( DbDatabaseMetadata database, DbTableMetadata fromTable, DbEntityTypeMappingFragment fragment) { // move the condition's column from the formTable to the table in fragment if (fromTable != fragment.Table) { fragment.ColumnConditions.Each( cc => { cc.Column = TableOperations.CopyColumnAndAnyConstraints( database, fromTable, fragment.Table, cc.Column, true, false); }); } }
private void WriteMappingFragmentElement(DbEntityTypeMappingFragment mappingFragment) { _xmlWriter.WriteStartElement(MslConstants.Element_MappingFragment); _xmlWriter.WriteAttributeString(MslConstants.Attribute_StoreEntitySet, mappingFragment.Table.Name); WritePropertyMappings(mappingFragment.PropertyMappings); foreach (var conditionColumn in mappingFragment.ColumnConditions) { WriteConditionElement(conditionColumn); } _xmlWriter.WriteEndElement(); }
/// <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; } }
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 static bool UpdateColumnNamesForTableSharing( DbDatabaseMapping databaseMapping, EdmEntityType entityType, DbTableMetadata toTable, DbEntityTypeMappingFragment fragment) { // Validate: this table can be used only if: // 1. The table is not used by any other type // 2. The table is used only by types in the same type hierarchy (TPH) // 3. There is a 1:1 relationship and the PK count and types match (Table Splitting) var typesSharingTable = FindAllTypesUsingTable(databaseMapping, toTable); var associationsToSharedTable = new Dictionary<EdmEntityType, List<EdmAssociationType>>(); foreach (var candidateType in typesSharingTable) { var oneToOneAssocations = FindAllOneToOneFKAssociationTypes( databaseMapping.Model, entityType, candidateType); var rootType = candidateType.GetRootType(); if (!associationsToSharedTable.ContainsKey(rootType)) { associationsToSharedTable.Add(rootType, oneToOneAssocations.ToList()); } else { associationsToSharedTable[rootType].AddRange(oneToOneAssocations); } } foreach (var candidateTypePair in associationsToSharedTable) { // Check if these types are in a TPH hierarchy if (candidateTypePair.Key != entityType.GetRootType() && candidateTypePair.Value.Count == 0) { var tableName = toTable.GetTableName(); throw Error.EntityMappingConfiguration_InvalidTableSharing( entityType.Name, candidateTypePair.Key.Name, tableName != null ? tableName.Name : toTable.DatabaseIdentifier); } } var allAssociations = associationsToSharedTable.Values.SelectMany(l => l); if (allAssociations.Any()) { var principalKeyNamesType = toTable.GetKeyNamesType(); if (principalKeyNamesType == null) { // grab a candidate var association = allAssociations.First(); principalKeyNamesType = association.Constraint.PrincipalEnd(association).EntityType; if (allAssociations.All(x => x.Constraint.PrincipalEnd(x).EntityType == principalKeyNamesType)) { toTable.SetKeyNamesType(principalKeyNamesType); } } // rename the columns in the fragment to match the principal keys var principalKeys = principalKeyNamesType.KeyProperties().ToArray(); var i = 0; foreach (var k in entityType.KeyProperties()) { var dependentColumn = fragment.PropertyMappings.Single(pm => pm.PropertyPath.First() == k).Column; dependentColumn.Name = principalKeys[i].Name; i++; } return true; } return false; }
private void ConfigureConditions( DbDatabaseMapping databaseMapping, EdmEntityType entityType, DbEntityTypeMappingFragment fragment, DbProviderManifest providerManifest) { if (ValueConditions.Any() || NullabilityConditions.Any()) { fragment.ColumnConditions.Clear(); foreach (var condition in ValueConditions) { condition.Configure(databaseMapping, fragment, entityType, providerManifest); } foreach (var condition in NullabilityConditions) { condition.Configure(databaseMapping, fragment, entityType); } } }
private DbTableMetadata FindOrCreateTargetTable( DbDatabaseMapping databaseMapping, DbEntityTypeMappingFragment fragment, EdmEntityType entityType, DbTableMetadata fromTable, out bool isTableSharing) { DbTableMetadata toTable; isTableSharing = false; if (TableName == null) { toTable = fragment.Table; } else { toTable = databaseMapping.Database.FindTableByName(TableName); if (toTable == null) { if (entityType.BaseType == null) { // Rule: base type's always own the fragment's initial table toTable = fragment.Table; } else { toTable = databaseMapping.Database.AddTable(TableName.Name, fromTable); } } // Validate this table can be used and update as needed if it is isTableSharing = UpdateColumnNamesForTableSharing(databaseMapping, entityType, toTable, fragment); fragment.Table = toTable; toTable.SetTableName(TableName); } return toTable; }
private static void MoveDefaultDiscriminator( DbEntityTypeMappingFragment fromFragment, DbEntityTypeMappingFragment toFragment) { var discriminatorColumn = fromFragment.GetDefaultDiscriminator(); if (discriminatorColumn != null) { var discriminator = fromFragment.ColumnConditions.SingleOrDefault( cc => cc.Column == discriminatorColumn); if (discriminator != null) { fromFragment.RemoveDefaultDiscriminatorAnnotation(); fromFragment.ColumnConditions.Remove(discriminator); toFragment.AddDiscriminatorCondition(discriminator.Column, discriminator.Value); toFragment.SetDefaultDiscriminator(discriminator.Column); } } }
private void ConfigureDefaultDiscriminator( EdmEntityType entityType, DbEntityTypeMappingFragment fragment, bool isSharingTableWithBase) { if ((entityType.BaseType != null && !isSharingTableWithBase) || ValueConditions.Any() || NullabilityConditions.Any()) { var discriminator = fragment.RemoveDefaultDiscriminatorCondition(); if (discriminator != null && entityType.BaseType != null) { discriminator.IsNullable = true; } } }
/// <summary> /// Makes sure only the required property mappings are present /// </summary> private static void ConfigureTypeMappings( TableMapping tableMapping, Dictionary<EdmEntityType, DbEntityTypeMapping> rootMappings, EdmEntityType entityType, DbEntityTypeMappingFragment propertiesTypeMappingFragment, DbEntityTypeMappingFragment conditionTypeMappingFragment) { var existingPropertyMappings = new List<DbEdmPropertyMapping>( propertiesTypeMappingFragment.PropertyMappings.Where(pm => !pm.Column.IsPrimaryKeyColumn)); var existingConditions = new List<DbColumnCondition>(propertiesTypeMappingFragment.ColumnConditions); foreach (var columnMapping in from cm in tableMapping.ColumnMappings from pm in cm.PropertyMappings where pm.EntityType == entityType select new { cm.Column, Property = pm }) { if (columnMapping.Property.PropertyPath != null && !IsRootTypeMapping( rootMappings, columnMapping.Property.EntityType, columnMapping.Property.PropertyPath)) { var existingPropertyMapping = propertiesTypeMappingFragment.PropertyMappings.SingleOrDefault( x => x.PropertyPath == columnMapping.Property.PropertyPath); if (existingPropertyMapping != null) { existingPropertyMappings.Remove(existingPropertyMapping); } else { existingPropertyMapping = new DbEdmPropertyMapping { Column = columnMapping.Column, PropertyPath = columnMapping.Property.PropertyPath }; propertiesTypeMappingFragment.PropertyMappings.Add(existingPropertyMapping); } } if (columnMapping.Property.Conditions != null) { foreach (var condition in columnMapping.Property.Conditions) { if (conditionTypeMappingFragment.ColumnConditions.Contains(condition)) { existingConditions.Remove(condition); } else if (!entityType.IsAbstract) { conditionTypeMappingFragment.ColumnConditions.Add(condition); } } } } // Any leftover mappings are removed foreach (var leftoverPropertyMapping in existingPropertyMappings) { propertiesTypeMappingFragment.PropertyMappings.Remove(leftoverPropertyMapping); } foreach (var leftoverCondition in existingConditions) { conditionTypeMappingFragment.ColumnConditions.Remove(leftoverCondition); } if (entityType.IsAbstract) { propertiesTypeMappingFragment.ColumnConditions.Clear(); } }
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 static void UpdatePropertyMappings( DbDatabaseMetadata database, DbTableMetadata fromTable, DbEntityTypeMappingFragment fragment, bool useExisting) { // move the column from the formTable to the table in fragment if (fromTable != fragment.Table) { fragment.PropertyMappings.Each( pm => UpdatePropertyMapping(database, pm, fromTable, fragment.Table, useExisting)); } }
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); } }
public static void MovePropertyMapping( DbDatabaseMetadata database, DbEntityTypeMappingFragment fromFragment, DbEntityTypeMappingFragment toFragment, DbEdmPropertyMapping propertyMapping, bool requiresUpdate, bool useExisting) { // move the column from the formTable to the table in fragment if (requiresUpdate && fromFragment.Table != toFragment.Table) { UpdatePropertyMapping(database, propertyMapping, fromFragment.Table, toFragment.Table, useExisting); } // move the propertyMapping fromFragment.PropertyMappings.Remove(propertyMapping); toFragment.PropertyMappings.Add(propertyMapping); }
public static void CopyPropertyMappingToFragment( DbEdmPropertyMapping propertyMapping, DbEntityTypeMappingFragment fragment, bool useExisting) { // Ensure column is in the fragment's table var column = TablePrimitiveOperations.IncludeColumn(fragment.Table, propertyMapping.Column, useExisting); // Add the property mapping fragment.PropertyMappings.Add( new DbEdmPropertyMapping { PropertyPath = propertyMapping.PropertyPath, Column = column }); }
public void Generate( EdmEntityType entityType, IEnumerable<EdmProperty> properties, DbEntitySetMapping entitySetMapping, DbEntityTypeMappingFragment entityTypeMappingFragment, IList<EdmProperty> propertyPath, bool createNewColumn) { Contract.Requires(entityType != null); Contract.Requires(properties != null); Contract.Requires(entityTypeMappingFragment != null); Contract.Requires(propertyPath != null); var rootDeclaredProperties = entityType.GetRootType().DeclaredProperties; foreach (var property in properties) { if (property.PropertyType.IsComplexType && propertyPath.Any( p => p.PropertyType.IsComplexType && (p.PropertyType.ComplexType == property.PropertyType.ComplexType))) { throw Error.CircularComplexTypeHierarchy(); } propertyPath.Add(property); if (property.PropertyType.IsComplexType) { Generate( entityType, property.PropertyType.ComplexType.DeclaredProperties, entitySetMapping, entityTypeMappingFragment, propertyPath, createNewColumn); } else { var tableColumn = entitySetMapping.EntityTypeMappings .SelectMany(etm => etm.TypeMappingFragments) .SelectMany(etmf => etmf.PropertyMappings) .Where(pm => pm.PropertyPath.SequenceEqual(propertyPath)) .Select(pm => pm.Column) .FirstOrDefault(); if (tableColumn == null || createNewColumn) { tableColumn = entityTypeMappingFragment.Table.AddColumn( string.Join("_", propertyPath.Select(p => p.Name))); MapTableColumn( property, tableColumn, !rootDeclaredProperties.Contains(propertyPath.First()), entityType.KeyProperties().Contains(property)); } entityTypeMappingFragment.PropertyMappings.Add( new DbEdmPropertyMapping { Column = tableColumn, PropertyPath = propertyPath.ToList() }); } propertyPath.Remove(property); } }