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));
        }
Esempio n. 2
0
        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);
        }
Esempio n. 4
0
        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));
        }
Esempio n. 7
0
        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);
        }
Esempio n. 10
0
        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));
        }
Esempio n. 11
0
        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);
        }
Esempio n. 12
0
        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)
            });
        }
Esempio n. 14
0
        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));
        }