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();
 }
Example #2
0
        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();
        }
Example #5
0
        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?
        }