public void FindFunctions_creates_function_descriptors_for_functions_returning_complex_types_non_composable()
            {
                var model = CreateModel();

                model.ConceptualModel.AddItem(CreateComplexType());

                var mockType = new Mock <Type>();

                mockType
                .Setup(t => t.GetMethods(It.IsAny <BindingFlags>()))
                .Returns(typeof(Fake)
                         .GetMethods()
                         .Where(m => m.Name == "StoredProcToComplexTypes")
                         .ToArray());

                var functionDescriptor =
                    new FunctionDiscovery(model, mockType.Object)
                    .FindFunctions().SingleOrDefault();

                Assert.NotNull(functionDescriptor);
                Assert.Equal("StoredProcToComplexTypes", functionDescriptor.Name);
                Assert.Equal(0, functionDescriptor.Parameters.Count());
                Assert.Equal("Model.TestComplexType", functionDescriptor.ReturnTypes[0].FullName);
                Assert.Equal(functionDescriptor.StoreFunctionKind, StoreFunctionKind.StoredProcedure);
            }
            public void FindFunctions_creates_function_descriptors_for_functions_taking_ObjectParameter_non_composable()
            {
                var model = CreateModel();

                model.ConceptualModel.AddItem(CreateComplexType());
                model.ConceptualModel.AddItem(CreateEnumType());

                var mockType = new Mock <Type>();

                mockType
                .Setup(t => t.GetMethods(It.IsAny <BindingFlags>()))
                .Returns(typeof(Fake)
                         .GetMethods()
                         .Where(m => m.Name == "StoredProcWithObjectParamater")
                         .ToArray());

                var functionDescriptor =
                    new FunctionDiscovery(model, mockType.Object)
                    .FindFunctions().SingleOrDefault();

                Assert.NotNull(functionDescriptor);
                Assert.Equal("StoredProcWithObjectParamater", functionDescriptor.Name);

                var param = functionDescriptor.Parameters.SingleOrDefault();

                Assert.NotNull(param);
                Assert.Equal("param", param.Name);
                Assert.Equal("Model.TestEnumType", param.EdmType.FullName);
                Assert.True(param.IsOutParam);
            }
            public void FindFunctions_creates_function_descriptors_taking_and_returning_nullable_enums()
            {
                var model = CreateModel();

                model.ConceptualModel.AddItem(CreateEnumType());

                var mockType = new Mock <Type>();

                mockType
                .Setup(t => t.GetMethods(It.IsAny <BindingFlags>()))
                .Returns(typeof(Fake)
                         .GetMethods()
                         .Where(m => m.Name == "EnumFunctionImportWithNullableEnums")
                         .ToArray());

                var functionDescriptor =
                    new FunctionDiscovery(model, mockType.Object)
                    .FindFunctions().SingleOrDefault();

                Assert.NotNull(functionDescriptor);
                Assert.Equal("EnumFunctionImportWithNullableEnums", functionDescriptor.Name);
                Assert.Equal(1, functionDescriptor.Parameters.Count());
                Assert.Equal("Model.TestEnumType", functionDescriptor.ReturnTypes[0].FullName);
                Assert.Equal(functionDescriptor.StoreFunctionKind, StoreFunctionKind.TableValuedFunction);
            }
            public void FindFunctions_ignores_empty_ResultTypes_for_non_composable()
            {
                var mockType = new Mock<Type>();
                mockType
                    .Setup(t => t.GetMethods(It.IsAny<BindingFlags>()))
                    .Returns(new[] {typeof (Fake).GetMethod("EmptyResultType")});

                var returnType = new FunctionDiscovery(CreateModel(), mockType.Object)
                    .FindFunctions()
                    .ToArray()[0].ReturnTypes[0];

                Assert.Contains("Edm.Int32", returnType.FullName);
            }
            public void FindFunctions_creates_function_descriptors_with_custom_names()
            {
                var mockType = new Mock<Type>();
                mockType
                    .Setup(t => t.GetMethods(It.IsAny<BindingFlags>()))
                    .Returns(typeof (Fake)
                        .GetMethods()
                        .Where(m => m.Name == "FuncWithDifferentNames")
                        .ToArray());

                var functionDescriptor =
                    new FunctionDiscovery(CreateModel(), mockType.Object)
                        .FindFunctions().Single();

                Assert.NotNull(functionDescriptor);
                Assert.Equal("storeFuncName", functionDescriptor.Name);
            }
            public void FindFunctions_creates_function_descriptors_for_built_in_function()
            {
                var mockType = new Mock<Type>();
                mockType
                    .Setup(t => t.GetMethods(It.IsAny<BindingFlags>()))
                    .Returns(new[] { typeof(Fake).GetMethod("BuiltInFunction") });

                var functionDescriptor =
                    new FunctionDiscovery(CreateModel(), mockType.Object)
                        .FindFunctions().SingleOrDefault();

                Assert.NotNull(functionDescriptor);
                Assert.Single(functionDescriptor.Parameters);
                Assert.Equal("param", functionDescriptor.Parameters.First().Name);
                Assert.Equal("Edm.String", functionDescriptor.Parameters.First().EdmType.FullName);
                Assert.Equal("Edm.Int32", functionDescriptor.ReturnTypes[0].FullName);
                Assert.True(functionDescriptor.IsBuiltIn);
            }
            public void FindFunctions_creates_function_descriptors_for_primitive_udfs()
            {
                var mockType = new Mock<Type>();
                mockType
                    .Setup(t => t.GetMethods(It.IsAny<BindingFlags>()))
                    .Returns(new[] { typeof(Fake).GetMethod("ScalarUdfPrimitiveType") });

                var functionDescriptor =
                    new FunctionDiscovery(CreateModel(), mockType.Object)
                        .FindFunctions().SingleOrDefault();

                Assert.NotNull(functionDescriptor);
                Assert.Single(functionDescriptor.Parameters);
                Assert.Equal("param", functionDescriptor.Parameters.First().Name);
                Assert.Equal("Edm.String", functionDescriptor.Parameters.First().EdmType.FullName);
                Assert.Equal("Edm.Int32", functionDescriptor.ReturnTypes[0].FullName);
                Assert.Equal(StoreFunctionKind.ScalarUserDefinedFunction, functionDescriptor.StoreFunctionKind);
            }
            public void FindFunctions_creates_function_private()
            {
                var mockType = new Mock<Type>();
                mockType
                    .Setup(t => t.GetMethods(It.IsAny<BindingFlags>()))
                    .Returns(typeof(Fake)
                        .GetMethods(BindingFlags.Instance | BindingFlags.NonPublic)
                        .Where(m => m.Name == "PrivateFunction")
                        .ToArray());

                var functionDescriptor =
                    new FunctionDiscovery(CreateModel(), mockType.Object)
                        .FindFunctions().Single();

                Assert.NotNull(functionDescriptor);
                Assert.Equal("PrivateFunction", functionDescriptor.Name);
                Assert.Single(functionDescriptor.Parameters);
                Assert.Equal("Edm.Int32", functionDescriptor.ReturnTypes[0].FullName);
                Assert.Equal(StoreFunctionKind.TableValuedFunction, functionDescriptor.StoreFunctionKind);
            }
            public void FindFunctions_creates_function_descriptors_returning_primitive_types()
            {
                var mockType = new Mock<Type>();
                mockType
                    .Setup(t => t.GetMethods(It.IsAny<BindingFlags>()))
                    .Returns(typeof (Fake)
                        .GetMethods()
                        .Where(m => m.Name == "PrimitiveFunctionImportComposable" || m.Name == "NotAFunctionImport")
                        .ToArray());

                var functionDescriptor =
                    new FunctionDiscovery(CreateModel(), mockType.Object)
                        .FindFunctions().Single();

                Assert.NotNull(functionDescriptor);
                Assert.Equal("PrimitiveFunctionImportComposable", functionDescriptor.Name);
                Assert.Equal(2, functionDescriptor.Parameters.Count());
                Assert.Equal("Edm.Int32", functionDescriptor.ReturnTypes[0].FullName);
                Assert.Equal(StoreFunctionKind.TableValuedFunction, functionDescriptor.StoreFunctionKind);
            }
        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);

                    if (functionImportDefinition.IsComposableAttribute)
                    {
                        model.ConceptualToStoreMapping.AddFunctionImportMapping(
                            new FunctionImportMappingComposable(
                                functionImportDefinition,
                                storeFunctionDefinition,
                                new FunctionImportResultMapping(),
                                model.ConceptualToStoreMapping));
                    }
                    else
                    {
                        model.ConceptualToStoreMapping.AddFunctionImportMapping(
                            new FunctionImportMappingNonComposable(
                                functionImportDefinition,
                                storeFunctionDefinition,
                                new FunctionImportResultMapping[0],
                                model.ConceptualToStoreMapping));
                    }
                }
            }

            // TODO: model defined functions?
        }
            public void FindFunctions_creates_function_descriptors_for_extension_methods()
            {
                var mockType = new Mock<Type>();
                mockType
                    .Setup(t => t.GetMethods(It.IsAny<BindingFlags>()))
                    .Returns(new[] {typeof (StaticFake).GetMethod("ExtensionMethod")});

                mockType
                    .Protected()
                    .Setup<TypeAttributes>("GetAttributeFlagsImpl")
                    .Returns(TypeAttributes.Abstract | TypeAttributes.Sealed);

                var functionDescriptor = new FunctionDiscovery(CreateModel(), mockType.Object)
                    .FindFunctions().SingleOrDefault();

                Assert.NotNull(functionDescriptor);
                Assert.Equal("ExtensionMethod", functionDescriptor.Name);
                Assert.Single(functionDescriptor.Parameters);
                Assert.Equal("param", functionDescriptor.Parameters.First().Name);
                Assert.Equal("Edm.String", functionDescriptor.Parameters.First().EdmType.FullName);
                Assert.Equal("Edm.Int32", functionDescriptor.ReturnTypes[0].FullName);
                Assert.Equal(StoreFunctionKind.TableValuedFunction, functionDescriptor.StoreFunctionKind);
            }
            public void FindFunctions_creates_function_descriptors_returning_complex_types()
            {
                var model = CreateModel();
                model.ConceptualModel.AddItem(CreateComplexType());

                var mockType = new Mock<Type>();
                mockType
                    .Setup(t => t.GetMethods(It.IsAny<BindingFlags>()))
                    .Returns(typeof (Fake)
                        .GetMethods()
                        .Where(m => m.Name == "FunctionImportReturningComplexTypesComposable")
                        .ToArray());

                var functionDescriptor =
                    new FunctionDiscovery(model, mockType.Object)
                        .FindFunctions().Single();

                Assert.NotNull(functionDescriptor);
                Assert.Equal("FunctionImportReturningComplexTypesComposable", functionDescriptor.Name);
                Assert.Empty(functionDescriptor.Parameters);
                Assert.Equal("Model.TestComplexType", functionDescriptor.ReturnTypes[0].FullName);
                Assert.Equal(StoreFunctionKind.TableValuedFunction, functionDescriptor.StoreFunctionKind);
            }
Beispiel #13
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?
        }