private IEnumerable <ParameterDescriptor> GetParameters(MethodInfo method, StoreFunctionKind storeFunctionKind)
        {
            Debug.Assert(method != null, "method is null");

            foreach (var parameter in method.GetParameters())
            {
                if (method.IsDefined(typeof(ExtensionAttribute), false) && parameter.Position == 0)
                {
                    continue;
                }

                if (parameter.IsOut || parameter.ParameterType.IsByRef)
                {
                    throw new InvalidOperationException(
                              $"The parameter '{parameter.Name}' of function '{method.Name}' is an out or ref parameter. To map Input/Output database parameters use the 'ObjectParameter' as the parameter type.");
                }

                var paramTypeAttribute =
                    (ParameterTypeAttribute)Attribute.GetCustomAttribute(parameter, typeof(ParameterTypeAttribute));

                var parameterType = parameter.ParameterType;

                var isObjectParameter = parameter.ParameterType == typeof(ObjectParameter);

                if (isObjectParameter)
                {
                    if (paramTypeAttribute == null)
                    {
                        throw new InvalidOperationException(
                                  $"Cannot infer type for parameter '{parameter.Name}' of funtion '{method.Name}'. All ObjectParameter parameters must be decorated with the ParameterTypeAttribute.");
                    }

                    parameterType = paramTypeAttribute.Type;
                }

                var unwrappedParameterType = Nullable.GetUnderlyingType(parameterType) ?? parameterType;

                var parameterEdmType =
                    unwrappedParameterType.IsEnum
                        ? FindEnumType(unwrappedParameterType)
                        : GetEdmPrimitiveTypeForClrType(unwrappedParameterType);

                if (parameterEdmType == null)
                {
                    throw new InvalidOperationException(
                              $"The type '{unwrappedParameterType.FullName}' of the parameter '{parameter.Name}' of function '{method.Name}' is invalid. Parameters can only be of a type that can be converted to an Edm scalar type");
                }

                if (storeFunctionKind == StoreFunctionKind.ScalarUserDefinedFunction &&
                    parameterEdmType.BuiltInTypeKind != BuiltInTypeKind.PrimitiveType)
                {
                    throw new InvalidOperationException(
                              $"The parameter '{parameter.Name}' of function '{method.Name}' is of the '{parameterEdmType}' type which is not an Edm primitive type. Types of parameters of store scalar functions must be Edm primitive types.");
                }

                yield return(new ParameterDescriptor(parameter.Name, parameterEdmType,
                                                     paramTypeAttribute != null ? paramTypeAttribute.StoreType : null, isObjectParameter));
            }
        }
Example #2
0
        public FunctionDescriptor(string name, IEnumerable<ParameterDescriptor> parameters,
            EdmType[] returnTypes, string resultColumnName, string databaseSchema, StoreFunctionKind storeFunctionKind)
        {
            Debug.Assert(!string.IsNullOrWhiteSpace(name), "invalid name");
            Debug.Assert(parameters != null, "parameters is null");
            Debug.Assert(parameters.All(p => p.EdmType != null), "invalid parameter type");
            Debug.Assert(returnTypes != null && returnTypes.Length > 0, "returnTypes array is null or empty");
            Debug.Assert(storeFunctionKind == StoreFunctionKind.StoredProcedure|| returnTypes.Length == 1, "multiple return types for non-sproc");

            _name = name;
            _returnTypes = returnTypes;
            _parameters = parameters.ToArray();
            _resultColumnName = resultColumnName;
            _databaseSchema = databaseSchema;
            _storeFunctionKind = storeFunctionKind;
        }
        public FunctionDescriptor(string name, IEnumerable <ParameterDescriptor> parameters,
                                  EdmType[] returnTypes, string resultColumnName, string databaseSchema, StoreFunctionKind storeFunctionKind)
        {
            Debug.Assert(!string.IsNullOrWhiteSpace(name), "invalid name");
            Debug.Assert(parameters != null, "parameters is null");
            Debug.Assert(parameters.All(p => p.EdmType != null), "invalid parameter type");
            Debug.Assert(returnTypes != null && returnTypes.Length > 0, "returnTypes array is null or empty");
            Debug.Assert(storeFunctionKind == StoreFunctionKind.StoredProcedure || returnTypes.Length == 1, "multiple return types for non-sproc");

            _name              = name;
            _returnTypes       = returnTypes;
            _parameters        = parameters.ToArray();
            _resultColumnName  = resultColumnName;
            _databaseSchema    = databaseSchema;
            _storeFunctionKind = storeFunctionKind;
        }
Example #4
0
        private EdmType[] GetReturnTypes(string methodName, Type methodReturnType,
            DbFunctionDetailsAttribute functionDetailsAttribute, StoreFunctionKind storeFunctionKind)
        {
            Debug.Assert(methodReturnType != null, "methodReturnType is null");

            var resultTypes = functionDetailsAttribute != null ? functionDetailsAttribute.ResultTypes : null;

            if (storeFunctionKind != StoreFunctionKind.StoredProcedure && resultTypes != null)
            {
                throw new InvalidOperationException(
                    "The DbFunctionDetailsAttribute.ResultTypes property should be used only for stored procedures returning multiple resultsets and must be null for composable function imports.");
            }

            resultTypes = resultTypes == null || resultTypes.Length == 0 ? null : resultTypes;

            if (resultTypes != null && resultTypes[0] != methodReturnType)
            {
                throw new InvalidOperationException(
                    string.Format(
                        "The ObjectResult<T> item type returned by the method '{0}' is '{1}' but the first type specified in the `DbFunctionDetailsAttribute.ResultTypes` is '{2}'. The ObjectResult<T> item type must match the first type from the `DbFunctionDetailsAttribute.ResultTypes` array.",
                        methodName, methodReturnType.FullName, resultTypes[0].FullName));
            }

            var edmResultTypes = (resultTypes ?? new[] {methodReturnType}).Select(GetReturnEdmItemType).ToArray();

            if (storeFunctionKind == StoreFunctionKind.ScalarUserDefinedFunction &&
                edmResultTypes[0].BuiltInTypeKind != BuiltInTypeKind.PrimitiveType)
            {
                throw new InvalidOperationException(
                    string.Format(
                        "The type '{0}' returned by the method '{1}' cannot be mapped to an Edm primitive type. Scalar user defined functions have to return types that can be mapped to Edm primitive types.",
                        methodReturnType.FullName, methodName));
            }

            return edmResultTypes;
        }
Example #5
0
        private IEnumerable<ParameterDescriptor> GetParameters(MethodInfo method, StoreFunctionKind storeFunctionKind)
        {
            Debug.Assert(method != null, "method is null");

            foreach (var parameter in method.GetParameters())
            {
                if (method.IsDefined(typeof(ExtensionAttribute), false) && parameter.Position == 0)
                {
                    continue;
                }

                if (parameter.IsOut || parameter.ParameterType.IsByRef)
                {
                    throw new InvalidOperationException(
                        string.Format(
                            "The parameter '{0}' is an out or ref parameter. To map Input/Output database parameters use the 'ObjectParameter' as the parameter type.",
                            parameter.Name));
                }

                var parameterType = parameter.ParameterType;

                var isObjectParameter = parameter.ParameterType == typeof (ObjectParameter);
                if (isObjectParameter)
                {
                    var paramType = (ParameterTypeAttribute)Attribute.GetCustomAttribute(parameter, typeof (ParameterTypeAttribute));

                    if (paramType == null)
                    {
                        throw new InvalidOperationException(
                            string.Format(
                                "Cannot infer type for parameter '{0}'. All ObjectParameter parameters must be decorated with the ParameterTypeAttribute.",
                                parameter.Name));
                    }

                    parameterType = paramType.Type;
                }

                var unwrappedParameterType = Nullable.GetUnderlyingType(parameterType) ?? parameterType;

                var parameterEdmType =
                    unwrappedParameterType.IsEnum
                        ? FindEnumType(unwrappedParameterType)
                        : GetEdmPrimitiveTypeForClrType(unwrappedParameterType);

                if (parameterEdmType == null)
                {
                    throw
                        new InvalidOperationException(
                            string.Format(
                                "The type '{0}' of the parameter '{1}' of function '{2}' is invalid. Parameters can only be of a type that can be converted to an Edm scalar type",
                                unwrappedParameterType.FullName, parameter.Name, method.Name));
                }

                if (storeFunctionKind == StoreFunctionKind.ScalarUserDefinedFunction &&
                    parameterEdmType.BuiltInTypeKind != BuiltInTypeKind.PrimitiveType)
                {
                    throw new InvalidOperationException(
                        string.Format(
                            "The parameter '{0}' is of the '{1}' type which is not an Edm primitive type. Types of parameters of store scalar functions must be Edm primitive types.",
                            parameter.Name, parameterEdmType));
                }

                yield return new ParameterDescriptor(parameter.Name, parameterEdmType, isObjectParameter);
            }
        }
        private EdmType[] GetReturnTypes(string methodName, Type methodReturnType,
                                         DbFunctionDetailsAttribute functionDetailsAttribute, StoreFunctionKind storeFunctionKind)
        {
            Debug.Assert(methodReturnType != null, "methodReturnType is null");

            var resultTypes = functionDetailsAttribute?.ResultTypes;

            if (storeFunctionKind != StoreFunctionKind.StoredProcedure && resultTypes != null)
            {
                throw new InvalidOperationException(
                          $"The DbFunctionDetailsAttribute.ResultTypes property should be used only for stored procedures returning multiple resultsets and must be null for composable function imports. Function: '{methodName}'");
            }

            resultTypes = resultTypes == null || resultTypes.Length == 0 ? null : resultTypes;

            if (resultTypes != null && resultTypes[0] != methodReturnType)
            {
                throw new InvalidOperationException(
                          $"The ObjectResult<T> item type returned by the function '{methodName}' is '{methodReturnType.FullName}' but the first type specified in the `DbFunctionDetailsAttribute.ResultTypes` is '{resultTypes[0].FullName}'. The ObjectResult<T> item type must match the first type from the `DbFunctionDetailsAttribute.ResultTypes` array.");
            }

            var edmResultTypes = (resultTypes ?? new[] { methodReturnType }).Select(GetReturnEdmItemType).ToArray();

            if (storeFunctionKind == StoreFunctionKind.ScalarUserDefinedFunction &&
                edmResultTypes[0].BuiltInTypeKind != BuiltInTypeKind.PrimitiveType)
            {
                throw new InvalidOperationException(
                          $"The type '{methodReturnType.FullName}' returned by the function '{methodName}' cannot be mapped to an Edm primitive type. Scalar user defined functions have to return types that can be mapped to Edm primitive types.");
            }

            return(edmResultTypes);
        }