private void WriteFunctionImportComplexTypeMappingElement( FunctionImportComplexTypeMapping complexTypeMapping) { this._xmlWriter.WriteStartElement("ComplexTypeMapping"); this._xmlWriter.WriteAttributeString("TypeName", complexTypeMapping.ReturnType.FullName); this.WriteFunctionImportPropertyMappingElements(complexTypeMapping.PropertyMappings.Cast <FunctionImportReturnTypeScalarPropertyMapping>()); this._xmlWriter.WriteEndElement(); }
private void WriteFunctionImportComplexTypeMappingElement(FunctionImportComplexTypeMapping complexTypeMapping) { DebugCheck.NotNull(complexTypeMapping); _xmlWriter.WriteStartElement(MslConstructs.ComplexTypeMappingElement); _xmlWriter.WriteAttributeString(MslConstructs.ComplexTypeMappingTypeNameAttribute, complexTypeMapping.ReturnType.FullName); WriteFunctionImportPropertyMappingElements( complexTypeMapping.PropertyMappings.Cast <FunctionImportReturnTypeScalarPropertyMapping>()); _xmlWriter.WriteEndElement(); }
private void CreateFunctionMappingComplexTypeMapping(CommandEntity entity, FunctionImportMapping importMapping) { //<ResultMapping> // <ComplexTypeMapping TypeName="PetShopModel.GetCategoryById_Result"> string entityName = String.Concat(entity.Name, "Result"); var mapping = importMapping.ResultMapping != null && importMapping.ResultMapping.ComplexTypeMappings != null ? importMapping.ResultMapping.ComplexTypeMappings.FirstOrDefault() : null; if (mapping == null) { importMapping.ResultMapping = new FunctionImportMappingResultMapping() { ComplexTypeMappings = new List <FunctionImportComplexTypeMapping>() }; mapping = new FunctionImportComplexTypeMapping() { TypeName = String.Concat(ConceptualSchema.Namespace, ".", entityName) }; importMapping.ResultMapping.ComplexTypeMappings.Add(mapping); } else if (!String.IsNullOrEmpty(mapping.TypeName)) { entityName = mapping.TypeName.Replace("IsTypeOf(", "").Replace(String.Format("{0}.", ConceptualSchema.Namespace), "").Replace(")", ""); entityName = entityName.Equals(entity.Name, StringComparison.OrdinalIgnoreCase) ? entity.Name : entityName; } if (ConceptualSchema.ComplexTypes.Count(c => c.Name.Equals(entityName, StringComparison.OrdinalIgnoreCase)) == 0) { entityName = String.Concat(entity.Name, "Result"); } // Check for inheritance. mapping.TypeName = String.Format("{0}.{1}", ConceptualSchema.Namespace, entityName); _mappingEntityNames.Add(entity.EntityKey(), importMapping.FunctionImportName); _mappingEntityNames.Add(entity.EntityKey() + "complex", entityName); //<ComplexTypeMapping TypeName="PetShopModel.GetCategoryById_Result"> // <ScalarProperty Name="CategoryId" ColumnName="CategoryId" /> // <ScalarProperty Name="Name" ColumnName="Name" /> // <ScalarProperty Name="Description" ColumnName="Descn" /> //</ComplexTypeMapping> MergeScalarProperties(mapping, entity); }
private void MergeScalarProperties(FunctionImportComplexTypeMapping mappingFragment, CommandEntity entity) { foreach (var property in mappingFragment.ScalarProperties.Where(p => entity.Properties.Count(prop => prop.KeyName.Equals(p.ColumnName, StringComparison.OrdinalIgnoreCase)) == 0)) { _mappingDroppedEntityPropertyNames[String.Format(PROPERTY_KEY, entity.EntityKeyName, property.ColumnName)] = property.Name; } var properties = new List <ScalarProperty>(); foreach (var property in entity.Properties) { var prop = mappingFragment.ScalarProperties.Where(p => p.ColumnName.Equals(property.KeyName, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); if (prop == null) { // The property doesn't exist so lets create it. prop = new ScalarProperty() { Name = property.Name }; } else if (!property.Name.Equals(prop.Name, StringComparison.OrdinalIgnoreCase)) // Column matches that in the database.. If the names are different, it wins. { // The propertyName has been updated. // TODO: Is there a better way to find out if they renamed the Property? //prop.Name = prop.Name; } else { // Update the propertyName so it is always current with SchemaHelper. prop.Name = property.Name; } prop.ColumnName = property.KeyName; if (!ExcludeProperty(property as ISchemaProperty) && properties.Count(p => p.Name.Equals(prop.Name, StringComparison.OrdinalIgnoreCase)) == 0) { properties.Add(prop); _mappingEntityPropertyNames[String.Format("{0}-{1}", entity.Name, property.KeyName)] = prop.Name; } } mappingFragment.ScalarProperties = properties.Distinct().ToList(); }
public void Apply(EntityContainer item, DbModel model) { var functionDescriptors = new FunctionDiscovery(model, _methodClassType).FindFunctions(); var storeFunctionBuilder = new StoreFunctionBuilder(model, _defaultSchema); foreach (var functionDescriptor in functionDescriptors) { var storeFunctionDefinition = storeFunctionBuilder.Create(functionDescriptor); model.StoreModel.AddItem(storeFunctionDefinition); if (functionDescriptor.StoreFunctionKind != StoreFunctionKind.ScalarUserDefinedFunction) { var functionImportDefinition = CreateFunctionImport(model, functionDescriptor); model.ConceptualModel.Container.AddFunctionImport(functionImportDefinition); List <FunctionImportResultMapping> resultMappings = new List <FunctionImportResultMapping>(); if (functionDescriptor.ReturnTypes.All(t => t is EntityType || t is ComplexType)) { foreach (EdmType returnType in functionDescriptor.ReturnTypes) { FunctionImportStructuralTypeMapping typeMapping; if (returnType is EntityType) { var entityType = (EntityType)returnType; var returnTypePropertyMappings = new Collection <FunctionImportReturnTypePropertyMapping>(); foreach (var propertyMapping in model.GetEntityTypePropertyMappings(entityType).OfType <ScalarPropertyMapping>()) { returnTypePropertyMappings.Add(new FunctionImportReturnTypeScalarPropertyMapping(propertyMapping.Property.Name, propertyMapping.Column.Name)); } typeMapping = new FunctionImportEntityTypeMapping( Enumerable.Empty <EntityType>(), new[] { entityType }, returnTypePropertyMappings, Enumerable.Empty <FunctionImportEntityTypeMappingCondition>()); } else // ComplexType { var complexType = (ComplexType)returnType; var returnTypePropertyMappings = new Collection <FunctionImportReturnTypePropertyMapping>(); foreach (var property in complexType.Properties) { returnTypePropertyMappings.Add(new FunctionImportReturnTypeScalarPropertyMapping(property.Name, property.Name)); } typeMapping = new FunctionImportComplexTypeMapping(complexType, returnTypePropertyMappings); } FunctionImportResultMapping resultMapping = new FunctionImportResultMapping(); resultMappings.Add(resultMapping); resultMapping.AddTypeMapping(typeMapping); } } if (functionImportDefinition.IsComposableAttribute) { model.ConceptualToStoreMapping.AddFunctionImportMapping( new FunctionImportMappingComposable( functionImportDefinition, storeFunctionDefinition, resultMappings.FirstOrDefault() ?? new FunctionImportResultMapping(), model.ConceptualToStoreMapping)); } else { // HACK: Currently, FunctionImportMappingNonComposable ctor does not support code-first construction because // it depends on EdmItemCollection being available from StorageMappingItemCollection. Code-first does // not create a StorageMappingItemCollection and, as a result, this ctor will throw a null reference // exception if any result mappings are passed to it in code-first context. This must be resolved in // EF itself. Until then, _only composable functions can support custom named column mappings_. Once // this issue is resolved in EF then the commented code should replace the current "empty array" // resultMapping parameter to enable custom mappings for non-composable functions as well: model.ConceptualToStoreMapping.AddFunctionImportMapping( new FunctionImportMappingNonComposable( functionImportDefinition, storeFunctionDefinition, // resultMappings.Any() ? resultMappings.ToArray() : new FunctionImportResultMapping[0], new FunctionImportResultMapping[0], model.ConceptualToStoreMapping)); } } } // TODO: model defined functions? }