如何使用动态LINQ求和
本文关键字:求和 LINQ 动态 何使用 | 更新日期: 2023-09-27 18:21:15
我有以下与动态linq库配合使用的功能:
string where = "Price < 5";
string orderby = "BookID ASC";
IQueryable<T> MyDataQueryable = _DataRawBase.AsQueryable<T>();
MyDataQueryable = MyDataQueryable.Where(where).OrderBy(orderby);
现在我想查询MyDataQueryable来对某些字段进行求和(可能还有求平均值)。
我该怎么做?
类似于:
double mysum = MyDataQueryable.Sum("Price");
那就太好了。。。
由于所有内容都是字符串类型,您可能需要尝试:
var myDataQueryable = _DataRawBase.AsQueryable<T>()
.Sum("Price");
采用以下扩展方法:
public static object Sum(this IQueryable source, string member)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (member == null) throw new ArgumentNullException(nameof(member));
// The most common variant of Queryable.Sum() expects a lambda.
// Since we just have a string to a property, we need to create a
// lambda from the string in order to pass it to the sum method.
// Lets create a ((TSource s) => s.Price ). First up, the parameter "s":
ParameterExpression parameter = Expression.Parameter(source.ElementType, "s");
// Followed by accessing the Price property of "s" (s.Price):
PropertyInfo property = source.ElementType.GetProperty(member);
MemberExpression getter = Expression.MakeMemberAccess(parameter, property);
// And finally, we create a lambda from that. First specifying on what
// to execute when the lambda is called, and finally the parameters of the lambda.
Expression selector = Expression.Lambda(getter, parameter);
// There are a lot of Queryable.Sum() overloads with different
// return types (double, int, decimal, double?, int?, etc...).
// We're going to find one that matches the type of our property.
MethodInfo sumMethod = typeof(Queryable).GetMethods().First(
m => m.Name == "Sum"
&& m.ReturnType == property.PropertyType
&& m.IsGenericMethod);
// Now that we have the correct method, we need to know how to call the method.
// Note that the Queryable.Sum<TSource>(source, selector) has a generic type,
// which we haven't resolved yet. Good thing is that we can use copy the one from
// our initial source expression.
var genericSumMethod = sumMethod.MakeGenericMethod(new[] { source.ElementType });
// TSource, source and selector are now all resolved. We now know how to call
// the sum-method. We're not going to call it here, we just express how we're going
// call it.
var callExpression = Expression.Call(
null,
genericSumMethod,
new[] {source.Expression, Expression.Quote(selector)});
// Pass it down to the query provider. This can be a simple LinqToObject-datasource,
// but also a more complex datasource (such as LinqToSql). Anyway, it knows what to
// do.
return source.Provider.Execute(callExpression);
}
这段代码对我有用:
浮动?fSum=qryQueryableData.Select("价格").Cast<浮动?>().Sum();
"价格"是一列类型为"浮动?"
此处提供解释。
我需要扩展Caramiriel的答案来处理字段:
public static object Sum(this IQueryable source, string member)
{
if (source == null) throw new ArgumentNullException("source");
if (member == null) throw new ArgumentNullException("member");
// Properties
PropertyInfo property = source.ElementType.GetProperty(member);
FieldInfo field = source.ElementType.GetField(member);
ParameterExpression parameter = Expression.Parameter(source.ElementType, "s");
Expression selector = Expression.Lambda(Expression.MakeMemberAccess(parameter, (MemberInfo)property ?? field), parameter);
// We've tried to find an expression of the type Expression<Func<TSource, TAcc>>,
// which is expressed as ( (TSource s) => s.Price );
// Method
MethodInfo sumMethod = typeof(Queryable).GetMethods().First(
m => m.Name == "Sum"
&& (property != null || field != null)
&& (property == null || m.ReturnType == property.PropertyType) // should match the type of the property
&& (field == null || m.ReturnType == field.FieldType) // should match the type of the property
&& m.IsGenericMethod);
return source.Provider.Execute(
Expression.Call(
null,
sumMethod.MakeGenericMethod(new[] { source.ElementType }),
new[] { source.Expression, Expression.Quote(selector) }));
}
尝试使用lambda表达式:
double mysum = MyDataQueryable.Sum(mdq => mdq.Price);