private EdmType CreateReturnRowType(string propertyName, EdmType edmType) { if (edmType.BuiltInTypeKind == BuiltInTypeKind.EntityType) { var propertyToSoreTypeUsage = FindStoreTypeUsages((EntityType)edmType); return (RowType.Create( ((EntityType)edmType).Properties.Select( m => EdmProperty.Create(m.Name, propertyToSoreTypeUsage[m])), null)); } if (edmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType) { return (RowType.Create( ((StructuralType)edmType).Members.Select( m => EdmProperty.Create(m.Name, GetStorePrimitiveTypeUsage(m.TypeUsage))), null)); } if (edmType.BuiltInTypeKind == BuiltInTypeKind.EnumType) { return(RowType.Create(new[] { EdmProperty.Create(propertyName, GetStorePrimitiveTypeUsage(TypeUsage.CreateDefaultTypeUsage(((EnumType)edmType).UnderlyingType))) }, null)); } return (RowType.Create( new[] { EdmProperty.Create(propertyName, GetStorePrimitiveTypeUsage(TypeUsage.CreateDefaultTypeUsage(edmType))) }, null)); }
private static EdmType CreateResultType(DbModel model, ResultDescriptor result) { EdmType edmType = GetSimpleEdmType(model, result.Type); if (edmType == null) { edmType = GetStructuralEdmType(model, result.Type); } if (edmType == null) { throw new InvalidOperationException(string.Format("Edm type is not found for result type {0}.", result.Type.FullName)); } switch (edmType.BuiltInTypeKind) { case BuiltInTypeKind.EntityType: var propertyMappings = ((EntityType)edmType).Properties.Join( model.ConceptualToStoreMapping.EntitySetMappings .SelectMany(t => t.EntityTypeMappings) .Where(t => edmType.Yield(e => e.BaseType, (e, b) => b, e => e != null).Contains(t.EntityType)) .SelectMany(tm => tm.Fragments.SelectMany(t => t.PropertyMappings)) .OfType <ScalarPropertyMapping>(), p => p, pm => pm.Property, (p, pm) => new { Property = p, TypeUsage = TypeUsage.Create(pm.Column.TypeUsage.EdmType, pm.Column.TypeUsage.Facets.Where(f => !new[] { "StoreGeneratedPattern", "ConcurrencyMode" }.Contains(f.Name))) }); return(RowType.Create(propertyMappings.Select(pm => EdmProperty.Create(pm.Property.Name, pm.TypeUsage)), null)); case BuiltInTypeKind.ComplexType: return(RowType.Create(((StructuralType)edmType).Members.Select(m => { string columnName = null; MetadataProperty metadata; //if (!m.MetadataProperties.TryGetValue("Configuration", true, out metadata) || !metadata.Value.TryGetProperty("ColumnName", out columnName)) if (m.MetadataProperties.TryGetValue("ClrAttributes", true, out metadata)) { var columnAttr = ((IEnumerable)m.MetadataProperties["ClrAttributes"].Value).OfType <ColumnAttribute>().SingleOrDefault(); if (columnAttr != null && !string.IsNullOrEmpty(columnAttr.Name)) { columnName = columnAttr.Name; } } return EdmProperty.Create(columnName ?? m.Name, model.ProviderManifest.GetStoreType(m.TypeUsage)); }), null)); case BuiltInTypeKind.EnumType: return(RowType.Create(new[] { EdmProperty.CreateEnum(result.ColumnName, (EnumType)edmType) }, null)); case BuiltInTypeKind.PrimitiveType: return(RowType.Create(new[] { EdmProperty.CreatePrimitive(result.ColumnName, (PrimitiveType)edmType) }, null)); default: throw new NotSupportedException(); } }
public void Can_create_composable_function_import_with_scalar_collection_result() { DbProviderManifest providerManifest; var containerMapping = GetContainerMapping(out providerManifest); var cTypeUsageString = TypeUsage.CreateDefaultTypeUsage( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String)); var sTypeUsageString = providerManifest.GetStoreType(cTypeUsageString); var rowType = RowType.Create( new[] { EdmProperty.Create("C", sTypeUsageString), }, null); var functionImport = EdmFunction.Create( "F", "N", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = true, ReturnParameters = new[] { FunctionParameter.Create("R", cTypeUsageString.EdmType.GetCollectionType(), ParameterMode.ReturnValue) } }, null); var targetFunction = EdmFunction.Create( "SF", "N", DataSpace.SSpace, new EdmFunctionPayload { IsComposable = true, ReturnParameters = new[] { FunctionParameter.Create("R", rowType.GetCollectionType(), ParameterMode.ReturnValue) } }, null); var resultMapping = new FunctionImportResultMapping(); var functionImportMapping = new FunctionImportMappingComposable( functionImport, targetFunction, resultMapping, containerMapping); Assert.Same(resultMapping, functionImportMapping.ResultMapping); Assert.Null(functionImportMapping.StructuralTypeMappings); Assert.Null(functionImportMapping.TvfKeys); }
public void CollectStoreModelErrors_returns_errors_from_function_return_rowtypes() { var edmSchemaError = new EdmSchemaError("msg", 42, EdmSchemaErrorSeverity.Error); var errorMetadataProperty = MetadataProperty.Create( MetadataItemHelper.SchemaErrorsMetadataPropertyName, TypeUsage.CreateDefaultTypeUsage( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String).GetCollectionType()), new List <EdmSchemaError> { edmSchemaError }); var rowType = RowType.Create(new EdmProperty[0], new[] { errorMetadataProperty }); var function = EdmFunction.Create( "foo", "bar", DataSpace.SSpace, new EdmFunctionPayload { ReturnParameters = new[] { FunctionParameter.Create( "ReturnType", rowType, ParameterMode.ReturnValue) } }, null); var model = new EdmModel(DataSpace.SSpace); model.AddItem(function); var schemaErrors = ModelGenerator.CollectStoreModelErrors(model); Assert.NotNull(schemaErrors); Assert.Equal(1, schemaErrors.Count); Assert.Same(edmSchemaError, schemaErrors.Single()); }
public void Build_does_not_try_map_not_mapped_functions() { var rowTypeProperty = CreateStoreProperty("p1", "int"); var storeFunction = EdmFunction.Create( "f_s", "storeModel", DataSpace.SSpace, new EdmFunctionPayload { IsComposable = true, IsFunctionImport = false, ReturnParameters = new[] { FunctionParameter.Create( "ReturnType", RowType.Create(new[] { rowTypeProperty }, null).GetCollectionType(), ParameterMode.ReturnValue) } }, null); var modelContainer = EntityContainer.Create("C_C", DataSpace.CSpace, new EntitySet[0], null, null); var storeContainer = EntityContainer.Create("C_S", DataSpace.SSpace, new EntitySet[0], null, null); var storeModel = EdmModel.CreateStoreModel(storeContainer, null, null); storeModel.AddItem(storeFunction); var mappingContext = new SimpleMappingContext(storeModel, true); mappingContext.AddMapping(storeContainer, modelContainer); var entityModel = DbDatabaseMappingBuilder.Build(mappingContext).ConceptualModel; Assert.NotNull(entityModel); Assert.Empty(entityModel.Containers.Single().FunctionImports); }
private RowType CreateRowTypeFromEntityType(EntityType entityType) { Debug.Assert(entityType != null, "entityType == null"); var types = Tools.GetTypeHierarchy(entityType); var entityTypeMappings = _model.ConceptualToStoreMapping.EntitySetMappings .SelectMany(s => s.EntityTypeMappings) .Where(t => types.Contains(t.EntityType)) .ToArray(); List <EdmProperty> rowTypeProperties = new List <EdmProperty>(); foreach (var property in entityType.Properties) { foreach (var entityTypeMapping in entityTypeMappings) { var propertyMapping = (ScalarPropertyMapping)entityTypeMapping.Fragments.SelectMany(f => f.PropertyMappings) .FirstOrDefault(p => p.Property == property); if (propertyMapping != null) { // we must use the column name and not just the name of the property to support custom column mappings rowTypeProperties.Add(EdmProperty.Create(propertyMapping.Column.Name, TypeUsage.Create( propertyMapping.Column.TypeUsage.EdmType, propertyMapping.Column.TypeUsage.Facets.Where( f => f.Name != "StoreGeneratedPattern" && f.Name != "ConcurrencyMode")))); break; } } } return(RowType.Create(rowTypeProperties, null)); }
private static IList <FunctionParameter> GetStoreReturnParameters( this DbModel model, MethodInfo methodInfo, FunctionAttribute functionAttribute) { ParameterInfo returnParameterInfo = methodInfo.ReturnParameter; if (returnParameterInfo == null || returnParameterInfo.ParameterType == typeof(void)) { throw new NotSupportedException($"The return type of {methodInfo.Name} is not supported."); } ParameterAttribute returnParameterAttribute = returnParameterInfo.GetCustomAttribute <ParameterAttribute>(); ResultTypeAttribute[] returnTypeAttributes = methodInfo.GetCustomAttributes <ResultTypeAttribute>().ToArray(); if (functionAttribute.Type == FunctionType.StoredProcedure) { if (returnParameterAttribute != null) { throw new NotSupportedException( $"{nameof(ParameterAttribute)} for return value of method {methodInfo.Name} is not supported."); } return(new FunctionParameter[0]); } if (returnTypeAttributes.Any()) { throw new NotSupportedException($"{nameof(ResultTypeAttribute)} for method {methodInfo.Name} is not supported."); } if (functionAttribute.Type == FunctionType.TableValuedFunction) { if (returnParameterAttribute != null) { throw new NotSupportedException( $"{nameof(ParameterAttribute)} for return value of method {methodInfo.Name} is not supported."); } /* * <CollectionType> * <RowType> * <Property Name="PersonID" Type="int" Nullable="false" /> * <Property Name="FirstName" Type="nvarchar" MaxLength="50" /> * <Property Name="LastName" Type="nvarchar" MaxLength="50" /> * <Property Name="JobTitle" Type="nvarchar" MaxLength="50" /> * <Property Name="BusinessEntityType" Type="nvarchar" MaxLength="50" /> * </RowType> * </CollectionType> */ // returnParameterInfo.ParameterType is IQueryable<T>. Type storeReturnParameterClrType = returnParameterInfo.ParameterType.GetGenericArguments().Single(); StructuralType modelReturnParameterStructuralType = model.GetModelStructualType( storeReturnParameterClrType, methodInfo); ComplexType modelReturnParameterComplexType = modelReturnParameterStructuralType as ComplexType; RowType storeReturnParameterRowType; if (modelReturnParameterComplexType != null) { storeReturnParameterRowType = RowType.Create( modelReturnParameterComplexType.Properties.Select(property => EdmProperty.Create(property.Name, model.ProviderManifest.GetStoreType(property.TypeUsage))), null); } else { EntityType modelReturnParameterEntityType = modelReturnParameterStructuralType as EntityType; if (modelReturnParameterEntityType != null) { storeReturnParameterRowType = RowType.Create( modelReturnParameterEntityType.Properties.Select(property => { var typeUsage = TypeUsage.Create(model.ProviderManifest.GetStoreType(property.TypeUsage).EdmType, property.TypeUsage.Facets); var result = EdmProperty.Create(property.Name, typeUsage); var propertyNames = new[] { nameof(EdmProperty.Name), nameof(EdmProperty.TypeUsage), nameof(EdmProperty.MetadataProperties) }; result.SetMetadataProperties(property.MetadataProperties.Where(m => !propertyNames.Contains(m.Name))); return(result); }), null); //storeReturnParameterRowType = RowType.Create( // modelReturnParameterEntityType.Properties.Select(property => property.Clone()), // null); } else { throw new NotSupportedException($"Structural type {modelReturnParameterStructuralType.FullName} of method {methodInfo.Name} cannot be converted to {nameof(RowType)}."); } } return(new FunctionParameter[] { FunctionParameter.Create( "ReturnType", storeReturnParameterRowType.GetCollectionType(), // Collection of RowType. ParameterMode.ReturnValue) }); } if (functionAttribute.Type == FunctionType.NonComposableScalarValuedFunction) { // Non-composable scalar-valued function. return(new FunctionParameter[0]); } // Composable scalar-valued/Aggregate/Built in/Niladic function. // <Function Name="ufnGetProductListPrice" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo" // ReturnType ="money"> PrimitiveType storeReturnParameterPrimitiveType = model.GetStoreParameterPrimitiveType(methodInfo, returnParameterInfo, functionAttribute); return(new FunctionParameter[] { FunctionParameter.Create("ReturnType", storeReturnParameterPrimitiveType, ParameterMode.ReturnValue) }); }
public void Can_create_composable_function_import_with_entity_type_hierarchy() { DbProviderManifest providerManifest; var containerMapping = GetContainerMapping(out providerManifest); var cTypeUsageInt = TypeUsage.Create( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32), new[] { Facet.Create(MetadataItem.NullableFacetDescription, false) }); var sTypeUsageInt = TypeUsage.Create( providerManifest.GetStoreType(cTypeUsageInt).EdmType, new[] { Facet.Create(MetadataItem.NullableFacetDescription, false) }); var cTypeUsageString = TypeUsage.CreateDefaultTypeUsage( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String)); var sTypeUsageString = providerManifest.GetStoreType(cTypeUsageString); var itemCollection = containerMapping.StorageMappingItemCollection.EdmItemCollection.GetItems <EntityType>(); var baseEntityType = itemCollection.Single(et => et.Name == "E"); var entityType1 = itemCollection.Single(et => et.Name == "E1"); var entityType2 = itemCollection.Single(et => et.Name == "E2"); var rowType = RowType.Create( new[] { EdmProperty.Create("CId", sTypeUsageInt), EdmProperty.Create("C", sTypeUsageString), EdmProperty.Create("C1", sTypeUsageString), EdmProperty.Create("C2", sTypeUsageString), EdmProperty.Create("CD", sTypeUsageString) }, null); var functionImport = EdmFunction.Create( "F", "N", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = true, ReturnParameters = new[] { FunctionParameter.Create("R", baseEntityType.GetCollectionType(), ParameterMode.ReturnValue) } }, null); var targetFunction = EdmFunction.Create( "SF", "N", DataSpace.SSpace, new EdmFunctionPayload { IsComposable = true, ReturnParameters = new[] { FunctionParameter.Create("R", rowType.GetCollectionType(), ParameterMode.ReturnValue) } }, null); var resultMapping = new FunctionImportResultMapping(); var typeMapping = new FunctionImportEntityTypeMapping( new[] { baseEntityType }, Enumerable.Empty <EntityType>(), new Collection <FunctionImportReturnTypePropertyMapping>() { new FunctionImportReturnTypeScalarPropertyMapping("Id", "CId"), new FunctionImportReturnTypeScalarPropertyMapping("P", "C"), new FunctionImportReturnTypeScalarPropertyMapping("Discriminator", "CD"), }, Enumerable.Empty <FunctionImportEntityTypeMappingConditionValue>()); resultMapping.AddTypeMapping(typeMapping); typeMapping = new FunctionImportEntityTypeMapping( Enumerable.Empty <EntityType>(), new[] { entityType1 }, new Collection <FunctionImportReturnTypePropertyMapping>() { new FunctionImportReturnTypeScalarPropertyMapping("P1", "C1"), }, new [] { new FunctionImportEntityTypeMappingConditionValue("CD", "E1") }); resultMapping.AddTypeMapping(typeMapping); typeMapping = new FunctionImportEntityTypeMapping( Enumerable.Empty <EntityType>(), new[] { entityType2 }, new Collection <FunctionImportReturnTypePropertyMapping>() { new FunctionImportReturnTypeScalarPropertyMapping("P2", "C2"), }, new [] { new FunctionImportEntityTypeMappingConditionValue("CD", "E2") }); resultMapping.AddTypeMapping(typeMapping); var functionImportMapping = new FunctionImportMappingComposable( functionImport, targetFunction, resultMapping, containerMapping); Assert.Same(resultMapping, functionImportMapping.ResultMapping); Assert.Equal(2, functionImportMapping.StructuralTypeMappings.Count); Assert.Equal(1, functionImportMapping.TvfKeys.Length); Assert.Equal(typeof(E1).Name, functionImportMapping.StructuralTypeMappings[0].Item1.Name); Assert.Equal(1, functionImportMapping.StructuralTypeMappings[0].Item2.Count()); Assert.Equal(3, functionImportMapping.StructuralTypeMappings[0].Item3.Count()); Assert.Equal(typeof(E2).Name, functionImportMapping.StructuralTypeMappings[1].Item1.Name); Assert.Equal(1, functionImportMapping.StructuralTypeMappings[0].Item2.Count()); Assert.Equal(3, functionImportMapping.StructuralTypeMappings[0].Item3.Count()); }
public void Can_create_composable_function_import_with_entity_type_collection_result() { DbProviderManifest providerManifest; var containerMapping = GetContainerMapping(out providerManifest); var cTypeUsageInt = TypeUsage.Create( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32), new[] { Facet.Create(MetadataItem.NullableFacetDescription, false) }); var sTypeUsageInt = TypeUsage.Create( providerManifest.GetStoreType(cTypeUsageInt).EdmType, new[] { Facet.Create(MetadataItem.NullableFacetDescription, false) }); var entityType = EntityType.Create( "RT", "N", DataSpace.CSpace, new[] { "PId" }, new[] { EdmProperty.Create("PId", cTypeUsageInt), EdmProperty.Create("P", cTypeUsageInt), }, null); var rowType = RowType.Create( new[] { EdmProperty.Create("CId", sTypeUsageInt), EdmProperty.Create("C", sTypeUsageInt), }, null); var functionImport = EdmFunction.Create( "F", "N", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = true, ReturnParameters = new[] { FunctionParameter.Create("R", entityType.GetCollectionType(), ParameterMode.ReturnValue) } }, null); var targetFunction = EdmFunction.Create( "SF", "N", DataSpace.SSpace, new EdmFunctionPayload { IsComposable = true, ReturnParameters = new[] { FunctionParameter.Create("R", rowType.GetCollectionType(), ParameterMode.ReturnValue) } }, null); var typeMapping = new FunctionImportEntityTypeMapping( Enumerable.Empty <EntityType>(), new[] { entityType }, new Collection <FunctionImportReturnTypePropertyMapping>() { new FunctionImportReturnTypeScalarPropertyMapping("PId", "CId"), new FunctionImportReturnTypeScalarPropertyMapping("P", "C"), }, Enumerable.Empty <FunctionImportEntityTypeMappingCondition>()); var resultMapping = new FunctionImportResultMapping(); resultMapping.AddTypeMapping(typeMapping); var functionImportMapping = new FunctionImportMappingComposable( functionImport, targetFunction, resultMapping, containerMapping); Assert.Same(resultMapping, functionImportMapping.ResultMapping); Assert.Equal(1, functionImportMapping.StructuralTypeMappings.Count); Assert.Equal(1, functionImportMapping.TvfKeys.Length); Assert.False(resultMapping.IsReadOnly); functionImportMapping.SetReadOnly(); Assert.True(resultMapping.IsReadOnly); }
public void Build_builds_valid_DbDatabaseMapping_for_functions() { var rowTypeProperty = CreateStoreProperty("p1", "int"); var complexTypeProperty = EdmProperty.Create( "p2", TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32))); var functionImportReturnComplexType = ComplexType.Create( "CT", "entityModel", DataSpace.CSpace, new[] { complexTypeProperty }, null); var storeFunction = EdmFunction.Create( "f_s", "storeModel", DataSpace.SSpace, new EdmFunctionPayload { IsComposable = true, IsFunctionImport = false, ReturnParameters = new[] { FunctionParameter.Create( "ReturnType", RowType.Create(new[] { rowTypeProperty }, null).GetCollectionType(), ParameterMode.ReturnValue) } }, null); var functionImport = EdmFunction.Create( "f_c", "entityModel", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = true, IsFunctionImport = true, ReturnParameters = new[] { FunctionParameter.Create( "ReturnType", functionImportReturnComplexType.GetCollectionType(), ParameterMode.ReturnValue) } }, null); var modelContainer = EntityContainer.Create("C_C", DataSpace.CSpace, new EntitySet[0], new[] { functionImport }, null); var storeContainer = EntityContainer.Create("C_S", DataSpace.SSpace, new EntitySet[0], null, null); var storeModel = EdmModel.CreateStoreModel(storeContainer, null, null); storeModel.AddItem(storeFunction); var mappingContext = new SimpleMappingContext(storeModel, true); mappingContext.AddMapping(rowTypeProperty, complexTypeProperty); mappingContext.AddMapping(storeFunction, functionImport); mappingContext.AddMapping(storeContainer, modelContainer); var entityModel = DbDatabaseMappingBuilder.Build(mappingContext).ConceptualModel; Assert.NotNull(entityModel); Assert.Equal(new[] { "f_c" }, entityModel.Containers.Single().FunctionImports.Select(f => f.Name)); Assert.Equal(new[] { "CT" }, entityModel.ComplexTypes.Select(t => t.Name)); }
public void BuildComposableFunctionMapping_creates_valid_function_mapping() { var rowTypeProperty = CreateStoreProperty("p1", "int"); var complexTypeProperty = EdmProperty.Create( "p2", TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32))); var functionImportReturnComplexType = ComplexType.Create( "c", "entityModel", DataSpace.CSpace, new[] { complexTypeProperty }, null); var storeFunction = EdmFunction.Create( "f_s", "storeModel", DataSpace.SSpace, new EdmFunctionPayload { IsComposable = true, IsFunctionImport = false, ReturnParameters = new[] { FunctionParameter.Create( "ReturnType", RowType.Create(new[] { rowTypeProperty }, null).GetCollectionType(), ParameterMode.ReturnValue) } }, null); var functionImport = EdmFunction.Create( "f_c", "entityModel", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = true, IsFunctionImport = false, ReturnParameters = new[] { FunctionParameter.Create( "ReturnType", functionImportReturnComplexType.GetCollectionType(), ParameterMode.ReturnValue) } }, null); var mappingContext = new SimpleMappingContext(new EdmModel(DataSpace.SSpace), true); mappingContext.AddMapping(rowTypeProperty, complexTypeProperty); mappingContext.AddMapping(storeFunction, functionImport); var functionImportMapping = DbDatabaseMappingBuilder.BuildComposableFunctionMapping(storeFunction, mappingContext); Assert.NotNull(functionImportMapping); Assert.Same(storeFunction, functionImportMapping.TargetFunction); Assert.Same(functionImport, functionImportMapping.FunctionImport); var structuralTypeMappings = functionImportMapping.StructuralTypeMappings; Assert.NotNull(structuralTypeMappings); Assert.Same(functionImportReturnComplexType, structuralTypeMappings.Single().Item1); Assert.Empty(structuralTypeMappings.Single().Item2); Assert.Same(complexTypeProperty, structuralTypeMappings.Single().Item3.Single().Property); Assert.Same(rowTypeProperty, ((ScalarPropertyMapping)structuralTypeMappings.Single().Item3.Single()).Column); }
private static DbCompiledModel CreateModel(NpgsqlConnection connection) { var dbModelBuilder = new DbModelBuilder(DbModelBuilderVersion.Latest); // Import Sets dbModelBuilder.Entity <Blog>(); dbModelBuilder.Entity <Post>(); dbModelBuilder.Entity <NoColumnsEntity>(); dbModelBuilder.Entity <User>(); dbModelBuilder.Entity <Editor>(); dbModelBuilder.Entity <Administrator>(); // Import function var dbModel = dbModelBuilder.Build(connection); var edmType = PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32); var addFunc = EdmFunction.Create( "ClrStoredAddFunction", "BloggingContext", DataSpace.SSpace, new EdmFunctionPayload { ParameterTypeSemantics = ParameterTypeSemantics.AllowImplicitConversion, Schema = "dbo", IsComposable = true, IsNiladic = false, IsBuiltIn = false, IsAggregate = false, IsFromProviderManifest = true, StoreFunctionName = "StoredAddFunction", ReturnParameters = new[] { FunctionParameter.Create("ReturnType", edmType, ParameterMode.ReturnValue) }, Parameters = new[] { FunctionParameter.Create("Value1", edmType, ParameterMode.In), FunctionParameter.Create("Value2", edmType, ParameterMode.In) } }, null); dbModel.StoreModel.AddItem(addFunc); var echoFunc = EdmFunction.Create( "StoredEchoFunction", "BloggingContext", DataSpace.SSpace, new EdmFunctionPayload { ParameterTypeSemantics = ParameterTypeSemantics.AllowImplicitConversion, Schema = "dbo", IsComposable = true, IsNiladic = false, IsBuiltIn = false, IsAggregate = false, IsFromProviderManifest = true, StoreFunctionName = null, // intentional ReturnParameters = new[] { FunctionParameter.Create("ReturnType", edmType, ParameterMode.ReturnValue) }, Parameters = new[] { FunctionParameter.Create("Value1", edmType, ParameterMode.In) } }, null); dbModel.StoreModel.AddItem(echoFunc); var stringStoreType = dbModel.ProviderManifest.GetStoreTypes().First(x => x.ClrEquivalentType == typeof(string)); var modelBlogStoreType = dbModel.StoreModel.EntityTypes.First(x => x.Name == typeof(Blog).Name); var rowType = RowType.Create( modelBlogStoreType.Properties.Select(x => { var clone = EdmProperty.Create(x.Name, x.TypeUsage); clone.CollectionKind = x.CollectionKind; clone.ConcurrencyMode = x.ConcurrencyMode; clone.IsFixedLength = x.IsFixedLength; clone.IsMaxLength = x.IsMaxLength; clone.IsUnicode = x.IsUnicode; clone.MaxLength = x.MaxLength; clone.Precision = x.Precision; clone.Scale = x.Scale; clone.StoreGeneratedPattern = x.StoreGeneratedPattern; clone.SetMetadataProperties(x .MetadataProperties .Where(metadataProerty => !clone .MetadataProperties .Any(cloneMetadataProperty => cloneMetadataProperty.Name.Equals(metadataProerty.Name)))); return(clone); }), null); var getBlogsFunc = EdmFunction.Create( "StoredGetBlogsFunction", "BloggingContext", DataSpace.SSpace, new EdmFunctionPayload { ParameterTypeSemantics = ParameterTypeSemantics.AllowImplicitConversion, Schema = "dbo", IsComposable = true, IsNiladic = false, IsBuiltIn = false, IsAggregate = false, StoreFunctionName = "GetBlogsByName", ReturnParameters = new[] { FunctionParameter.Create("ReturnType1", rowType.GetCollectionType(), ParameterMode.ReturnValue) }, Parameters = new[] { FunctionParameter.Create("Name", stringStoreType, ParameterMode.In) } }, null); dbModel.StoreModel.AddItem(getBlogsFunc); var stringPrimitiveType = PrimitiveType.GetEdmPrimitiveTypes().First(x => x.ClrEquivalentType == typeof(string)); var modelBlogConceptualType = dbModel.ConceptualModel.EntityTypes.First(x => x.Name == typeof(Blog).Name); EdmFunction getBlogsFuncModel = EdmFunction.Create( "GetBlogsByName", dbModel.ConceptualModel.Container.Name, DataSpace.CSpace, new EdmFunctionPayload { IsFunctionImport = true, IsComposable = true, Parameters = new[] { FunctionParameter.Create("Name", stringPrimitiveType, ParameterMode.In) }, ReturnParameters = new[] { FunctionParameter.Create("ReturnType1", modelBlogConceptualType.GetCollectionType(), ParameterMode.ReturnValue) }, EntitySets = new[] { dbModel.ConceptualModel.Container.EntitySets.First(x => x.ElementType == modelBlogConceptualType) } }, null); dbModel.ConceptualModel.Container.AddFunctionImport(getBlogsFuncModel); dbModel.ConceptualToStoreMapping.AddFunctionImportMapping(new FunctionImportMappingComposable( getBlogsFuncModel, getBlogsFunc, new FunctionImportResultMapping(), dbModel.ConceptualToStoreMapping)); var compiledModel = dbModel.Compile(); return(compiledModel); }
private static IList <FunctionParameter> GetStoreReturnParameters(DbModel model, MethodInfo methodInfo, FunctionAttribute functionAttribute) { if (methodInfo.ReturnParameter == null || (methodInfo.ReturnParameter.ParameterType == typeof(void) && functionAttribute.Type != FunctionType.StoredProcedure)) { throw new NotSupportedException(string.Format("The return type of {0} is not supported.", methodInfo.Name)); } var returnParameterAttribute = methodInfo.ReturnParameter.GetCustomAttribute <ParameterAttribute>(); //var returnTypeAttributes = methodInfo.GetCustomAttributes<ResultTypeAttribute>(); if (functionAttribute.Type == FunctionType.StoredProcedure || functionAttribute.Type == FunctionType.TableValuedFunction) { if (returnParameterAttribute != null) { throw new NotSupportedException(string.Format("ParameterAttribute for return value of method {0} is not supported.", methodInfo.Name)); } } if (functionAttribute.Type == FunctionType.StoredProcedure || methodInfo.ReturnType == typeof(void)) { //Stored Procedure return(new FunctionParameter[0]); //return new[] //{ // FunctionParameter.Create("ReturnType", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32), ParameterMode.ReturnValue) //}; } //if (returnTypeAttributes.Length > 0) // throw new NotSupportedException(string.Format("ResultTypeAttribute for method {0} is not supported.", methodInfo.Name)); if (functionAttribute.Type == FunctionType.TableValuedFunction) { //if (returnParameterAttribute != null) // throw new NotSupportedException(string.Format("ParameterAttribute for return value of method {0} is not supported.", methodInfo.Name)); /* * <CollectionType> * <RowType> * <Property Name="PersonID" Type="int" Nullable="false" /> * <Property Name="FirstName" Type="nvarchar" MaxLength="50" /> * <Property Name="LastName" Type="nvarchar" MaxLength="50" /> * <Property Name="JobTitle" Type="nvarchar" MaxLength="50" /> * <Property Name="BusinessEntityType" Type="nvarchar" MaxLength="50" /> * </RowType> * </CollectionType> */ // returnParameterInfo.ParameterType is IQueryable<T>. var storeReturnParameterClrType = methodInfo.ReturnParameter.ParameterType.GetGenericArguments().Single(); var modelReturnParameterStructuralType = GetModelStructualType(model, storeReturnParameterClrType, methodInfo); var modelReturnParameterComplexType = modelReturnParameterStructuralType as ComplexType; RowType storeReturnParameterRowType = null; if (modelReturnParameterComplexType != null) { storeReturnParameterRowType = RowType.Create( modelReturnParameterComplexType.Properties.Select(property => EdmProperty.Create(property.Name, model.ProviderManifest.GetStoreType(property.TypeUsage))), null); } else { var modelReturnParameterEntityType = modelReturnParameterStructuralType as EntityType; if (modelReturnParameterEntityType != null) { storeReturnParameterRowType = RowType.Create( modelReturnParameterEntityType.Properties.Select(property => CloneEdmProperty(property)), null); } else { throw new NotSupportedException(string.Format("Structural type {0} of method {1} cannot be converted to RowType.", modelReturnParameterStructuralType.FullName, methodInfo.Name)); } } return(new[] { FunctionParameter.Create( "ReturnType", storeReturnParameterRowType.GetCollectionType(), // Collection of RowType. ParameterMode.ReturnValue) }); } //if (functionAttribute.Type == FunctionType.NonComposableScalarValuedFunction) //{ // // Non-composable scalar-valued function. // return new FunctionParameter[0]; //} // Composable scalar-valued/Aggregate/Built in/Niladic function. // <Function Name="ufnGetProductListPrice" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo" // ReturnType ="money"> var storeReturnParameterPrimitiveType = GetStoreParameterPrimitiveType(model, methodInfo, methodInfo.ReturnParameter, functionAttribute); return(new[] { FunctionParameter.Create("ReturnType", storeReturnParameterPrimitiveType, ParameterMode.ReturnValue) }); }
public void Can_create_non_composable_function_with_multiple_results() { DbProviderManifest providerManifest; var containerMapping = GetContainerMapping(out providerManifest); var cTypeUsageInt = TypeUsage.Create( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32), new[] { Facet.Create(MetadataItem.NullableFacetDescription, false) }); var sTypeUsageInt = TypeUsage.Create( providerManifest.GetStoreType(cTypeUsageInt).EdmType, new[] { Facet.Create(MetadataItem.NullableFacetDescription, false) }); var cTypeUsageString = TypeUsage.CreateDefaultTypeUsage( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String)); var sTypeUsageString = providerManifest.GetStoreType(cTypeUsageString); var complexType = ComplexType.Create( "RT1", "N", DataSpace.CSpace, new[] { EdmProperty.Create("P1", cTypeUsageInt), EdmProperty.Create("P2", cTypeUsageString) }, null); var entityType = EntityType.Create( "RT2", "N", DataSpace.CSpace, new[] { "P3" }, new[] { EdmProperty.Create("P3", cTypeUsageInt), EdmProperty.Create("P4", cTypeUsageString), }, null); var rowType1 = RowType.Create( new[] { EdmProperty.Create("C1", sTypeUsageInt), EdmProperty.Create("C2", sTypeUsageString) }, null); var rowType2 = RowType.Create( new[] { EdmProperty.Create("C3", sTypeUsageInt), EdmProperty.Create("C4", sTypeUsageString) }, null); var functionImport = EdmFunction.Create( "F", "N", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = false, ReturnParameters = new[] { FunctionParameter.Create("R1", complexType.GetCollectionType(), ParameterMode.ReturnValue), FunctionParameter.Create("R2", entityType.GetCollectionType(), ParameterMode.ReturnValue) }, EntitySets = new[] { new EntitySet(), new EntitySet() } }, null); var targetFunction = EdmFunction.Create( "SF", "N", DataSpace.SSpace, new EdmFunctionPayload { IsComposable = false, ReturnParameters = new[] { FunctionParameter.Create("R1", rowType1.GetCollectionType(), ParameterMode.ReturnValue), FunctionParameter.Create("R2", rowType2.GetCollectionType(), ParameterMode.ReturnValue) }, EntitySets = new [] { new EntitySet(), new EntitySet() } }, null); var resultMappings = new List <FunctionImportResultMapping> { new FunctionImportResultMapping(), new FunctionImportResultMapping() }; resultMappings[0].AddTypeMapping(new FunctionImportComplexTypeMapping( complexType, new Collection <FunctionImportReturnTypePropertyMapping>() { new FunctionImportReturnTypeScalarPropertyMapping("P1", "C1"), new FunctionImportReturnTypeScalarPropertyMapping("P2", "C2"), })); resultMappings[1].AddTypeMapping(new FunctionImportEntityTypeMapping( Enumerable.Empty <EntityType>(), new [] { entityType }, new Collection <FunctionImportReturnTypePropertyMapping>() { new FunctionImportReturnTypeScalarPropertyMapping("P3", "C3"), new FunctionImportReturnTypeScalarPropertyMapping("P4", "C4") }, Enumerable.Empty <FunctionImportEntityTypeMappingCondition>())); var functionImportMapping = new FunctionImportMappingNonComposable( functionImport, targetFunction, resultMappings, containerMapping); Assert.Equal(resultMappings.Count, functionImportMapping.ResultMappings.Count); functionImportMapping.ResultMappings.Each(m => Assert.False(m.IsReadOnly)); functionImportMapping.SetReadOnly(); functionImportMapping.ResultMappings.Each(m => Assert.True(m.IsReadOnly)); }