How to call sql scalar function in Expression tree of linq queryable?

送分小仙女□ 提交于 2019-12-24 00:48:27

问题


I am creating lambda expression for Iqueryable to get value from a collection but I want to convert that value to other datatype like int or decimal. So as I cannot use c# casting with Iqueryable so I have created user defined scalar function in sql and trying to access that in expression but it throws exception that the 'methodname' cannot be converted to sql expression.

public class Context
{

[DbFunction("dbo", "ConvertToDouble")]
        public int? ConvertToDouble(string value)
        {
            var sql = $"set @result = dbo.[ConvertToDouble]('{value}')";
            var output = new SqlParameter { ParameterName = @"result", DbType = DbType.Int32, Size = 16, Direction = ParameterDirection.Output };
            var result = Database.ExecuteSqlCommand(sql, output);
            return output.Value as int?;
        }
}


private static Expression<Func<TSource, TDataType>> CreateLamdaExpression<TSource, TDataType>(string fieldName)
        {
            var parameterExpression = Expression.Parameter(typeof(TSource));

            var collectionParameter = Expression.Property(parameterExpression, "CustomFieldValues");
            var childType = collectionParameter.Type.GetGenericArguments()[0];
            var propertyParameter = Expression.Parameter(childType, childType.Name);

            var left = Expression.Property(propertyParameter, "Name");
            var right = Expression.Constant(fieldName);

            var innerLambda = Expression.Equal(left, right);

            var innerFunction = Expression.Lambda(innerLambda, propertyParameter);

            var method = typeof(Enumerable).GetMethods().Where(m => m.Name == "FirstOrDefault" && m.GetParameters().Length == 2).FirstOrDefault().MakeGenericMethod(typeof(CustomFieldValue));

            var outerLambda = Expression.Call(method, Expression.Property(parameterExpression, collectionParameter.Member as System.Reflection.PropertyInfo), innerFunction);
            var propertyGetter = Expression.Property(outerLambda, "Value");

            if (typeof(TDataType) != typeof(object))
            {
               /var changeTypeCall = Expression.Call(Expression.Constant(Context), Context.GetType().GetMethod("ConvertToDouble", BindingFlags.Public | BindingFlags.Instance),
                                                            propertyGetter
                                                               );

                Expression convert = Expression.Convert(changeTypeCall,
                                                        typeof(TDataType));

                return Expression.Lambda<Func<TSource, TDataType>>(convert, new ParameterExpression[] { parameterExpression });
            }

            var result = Expression.Lambda<Func<TSource, TDataType>>(propertyGetter, new ParameterExpression[] { parameterExpression });
            return result;
        }

来源:https://stackoverflow.com/questions/55684233/how-to-call-sql-scalar-function-in-expression-tree-of-linq-queryable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!