Exemple #1
0
        private static PrimitiveType GetModelParameterPrimitiveType(
            this DbModel model, MethodInfo methodInfo, ParameterInfo parameterInfo)
        {
            // <Parameter Name="PersonID" Mode="In" Type="Int32" />
            Type parameterClrType = parameterInfo.ParameterType;
            ParameterAttribute parameterAttribute = parameterInfo.GetCustomAttribute <ParameterAttribute>();
            Type parameterAttributeClrType        = parameterAttribute?.ClrType;

            if (parameterClrType == typeof(ObjectParameter))
            {
                // ObjectParameter.Type is available only when methodInfo is called.
                // When building model, its store type/clr type must be provided by ParameterAttribute.
                if (parameterAttributeClrType == null)
                {
                    throw new NotSupportedException(
                              $"Parameter {parameterInfo.Name} of method {methodInfo.Name} is not supported. {nameof(ObjectParameter)} parameter must have {nameof(ParameterAttribute)} with {nameof(ParameterAttribute.ClrType)} specified.");
                }

                parameterClrType = parameterAttributeClrType;
            }
            else
            {
                // When parameter is not ObjectParameter, ParameterAttribute.ClrType should be the same as parameterClrType, or not specified.
                if (parameterAttributeClrType != null && parameterAttributeClrType != parameterClrType)
                {
                    throw new NotSupportedException(
                              $"Parameter {parameterInfo.Name} of method {methodInfo.Name} if of {parameterClrType.FullName}, but its {nameof(ParameterAttribute)}.{nameof(ParameterAttribute.ClrType)} has a different type {parameterAttributeClrType.FullName}");
                }
            }

            return(model.GetModelPrimitiveType(parameterClrType, methodInfo));
        }
Exemple #2
0
        private static string GetStoreCommandText(this MethodInfo methodInfo, FunctionAttribute functionAttribute, string functionName)
        {
            if (functionAttribute.Type == FunctionType.NonComposableScalarValuedFunction)
            {
                string schema = functionAttribute.Schema;
                schema = string.IsNullOrWhiteSpace(schema) ? string.Empty : $"[{schema}].";
                IEnumerable <string> parameterNames = methodInfo
                                                      .GetParameters()
                                                      .Select(parameterInfo =>
                {
                    ParameterAttribute parameterAttribute = parameterInfo.GetCustomAttribute <ParameterAttribute>();
                    string parameterName = parameterAttribute?.Name;
                    return(string.IsNullOrWhiteSpace(parameterName) ? parameterInfo.Name : parameterName);
                })
                                                      .Select(parameterName => $"@{parameterName}");
                return($"SELECT {schema}[{functionName}]({string.Join(", ", parameterNames)})");
            }

            return(null);
        }
Exemple #3
0
        private static IList <FunctionParameter> GetModelReturnParameters(
            this DbModel model, MethodInfo methodInfo, FunctionAttribute functionAttribute)
        {
            ParameterInfo returnParameterInfo = methodInfo.ReturnParameter;

            if (returnParameterInfo == null || returnParameterInfo.ParameterType == typeof(void))
            {
                throw new NotSupportedException($"The return parameter type of {methodInfo.Name} is not supported.");
            }

            ParameterAttribute returnParameterAttribute = returnParameterInfo.GetCustomAttribute <ParameterAttribute>();

            ResultTypeAttribute[] returnTypeAttributes = methodInfo.GetCustomAttributes <ResultTypeAttribute>().ToArray();
            IEnumerable <EdmType> modelReturnParameterEdmTypes;

            if (functionAttribute.Type == FunctionType.StoredProcedure)
            {
                if (returnParameterAttribute != null)
                {
                    throw new NotSupportedException(
                              $"{nameof(ParameterAttribute)} for method {methodInfo.Name} is not supported.");
                }

                modelReturnParameterEdmTypes = methodInfo
                                               .GetStoredProcedureReturnTypes()
                                               .Select(clrType => model.GetModelStructualType(clrType, methodInfo));
            }
            else
            {
                if (returnTypeAttributes.Any())
                {
                    throw new NotSupportedException(
                              $"{nameof(ResultTypeAttribute)} for method {methodInfo.Name} is not supported.");
                }

                if (functionAttribute.Type == FunctionType.TableValuedFunction)
                {
                    // returnParameterInfo.ParameterType is IQueryable<T>.
                    Type           returnParameterClrType             = returnParameterInfo.ParameterType.GetGenericArguments().Single();
                    StructuralType modelReturnParameterStructuralType = model.GetModelStructualType(returnParameterClrType, methodInfo);
                    modelReturnParameterEdmTypes = Enumerable.Repeat(modelReturnParameterStructuralType, 1);
                }
                else
                {
                    Type returnParameterClrType          = returnParameterInfo.ParameterType;
                    Type returnParameterAttributeClrType = returnParameterAttribute?.ClrType;
                    if (returnParameterAttributeClrType != null &&
                        returnParameterAttributeClrType != returnParameterClrType)
                    {
                        throw new NotSupportedException(
                                  $"Return parameter of method {methodInfo.Name} is of {returnParameterClrType.FullName}, but its {nameof(ParameterAttribute)}.{nameof(ParameterAttribute.ClrType)} has a different type {returnParameterAttributeClrType.FullName}");
                    }

                    PrimitiveType returnParameterPrimitiveType = model.GetModelPrimitiveType(returnParameterClrType, methodInfo);
                    modelReturnParameterEdmTypes = Enumerable.Repeat(returnParameterPrimitiveType, 1);
                }
            }

            return(modelReturnParameterEdmTypes
                   .Select((edmType, index) => FunctionParameter.Create(
                               $"ReturnType{index}",
                               functionAttribute.Type == FunctionType.ModelDefinedFunction ? edmType : edmType.GetCollectionType(),
                               ParameterMode.ReturnValue))
                   .ToArray());
        }
Exemple #4
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)
            });
        }
Exemple #5
0
        private static PrimitiveType GetStoreParameterPrimitiveType(
            this DbModel model, MethodInfo methodInfo, ParameterInfo parameterInfo, FunctionAttribute functionAttribute)
        {
            // <Parameter Name="PersonID" Type="int" Mode="In" />
            Type parameterClrType = parameterInfo.ParameterType;
            ParameterAttribute parameterAttribute = parameterInfo.GetCustomAttribute <ParameterAttribute>();
            Type parameterAttributeClrType        = parameterAttribute?.ClrType;

            if (parameterClrType.IsGenericType)
            {
                Type parameterClrTypeDefinition = parameterClrType.GetGenericTypeDefinition();
                if (parameterClrTypeDefinition == typeof(IEnumerable <>) ||
                    parameterClrTypeDefinition == typeof(IQueryable <>))
                {
                    if (functionAttribute.Type == FunctionType.AggregateFunction)
                    {
                        // Aggregate function has one IEnumerable<T> or IQueryable<T> parameter.
                        parameterClrType = parameterClrType.GetGenericArguments().Single();
                    }
                    else
                    {
                        throw new NotSupportedException(
                                  $"Parameter {parameterInfo.Name} of method {methodInfo.Name} is not supported. {typeof(IEnumerable<>).FullName} parameter must be used for {nameof(FunctionType)}.{nameof(FunctionType.AggregateFunction)} method.");
                    }
                }
            }

            if (parameterClrType == typeof(ObjectParameter))
            {
                // ObjectParameter must be used for stored procedure parameter.
                if (functionAttribute.Type != FunctionType.StoredProcedure)
                {
                    throw new NotSupportedException(
                              $"Parameter {parameterInfo.Name} of method {methodInfo.Name} is not supported. {nameof(ObjectParameter)} parameter must be used for {nameof(FunctionType)}.{nameof(FunctionType.StoredProcedure)} method.");
                }

                // ObjectParameter.Type is available only when methodInfo is called.
                // When building model, its store type/clr type must be provided by ParameterAttribute.
                if (parameterAttributeClrType == null)
                {
                    throw new NotSupportedException(
                              $"Parameter {parameterInfo.Name} of method {methodInfo.Name} is not supported. {nameof(ObjectParameter)} parameter must have {nameof(ParameterAttribute)} with {nameof(ParameterAttribute.ClrType)} specified, with optional {nameof(ParameterAttribute.DbType)}.");
                }

                parameterClrType = parameterAttributeClrType;
            }
            else
            {
                // When parameter is not ObjectParameter, ParameterAttribute.ClrType should be either not specified, or the same as parameterClrType.
                if (parameterAttributeClrType != null && parameterAttributeClrType != parameterClrType)
                {
                    throw new NotSupportedException(
                              $"Parameter {parameterInfo.Name} of method {methodInfo.Name} is not supported. It is of {parameterClrType.FullName} type, but its {nameof(ParameterAttribute)}.{nameof(ParameterAttribute.ClrType)} has a different type {parameterAttributeClrType.FullName}");
                }
            }

            string storePrimitiveTypeName = parameterAttribute?.DbType;

            return(!string.IsNullOrEmpty(storePrimitiveTypeName)
                ? model.GetStorePrimitiveType(storePrimitiveTypeName, methodInfo, parameterInfo)
                : model.GetStorePrimitiveType(parameterClrType, methodInfo, parameterInfo));
        }