How to generate dynamic LINQ queries with GroupBy and Aggregates (SUM, COUNT, AVG)? -
the following code generates dynamic linq queries simple .where clauses involving field , value. extend class able generate groupby , equivalent of "having sum(amountfield)" or "having count(field)".
in essence should generate equivalent of:
_people.groupby(c => c.name) .where(grp => grp.count() > 1) .select(grp => grp.key);
or
_orders.groupby(c => c.custid) .where(grp => grp.sum(x => x.amount) > 100) .select(grp => grp.key);
can help? here code i'm using:
public class expressioncriteria<t> { list<expressioncriterion> _expressioncriterion = new list<expressioncriterion>(); private string _andor = "and"; public expressioncriteria<t> and() { _andor = "and"; return this; } public expressioncriteria<t> or() { _andor = "or"; return this; } public expressioncriteria<t> add(string propertyname, object value, expressiontype oper) { var newcriterion = new expressioncriterion(propertyname, value, oper, _andor); _expressioncriterion.add(newcriterion); return this; } private class expressioncriterion { public string propertyname { get; set; } public object value { get; set; } public expressiontype oper { get; set; } public string andor { get; set; } public expressioncriterion(string propertyname, object value, expressiontype oper, string andor = "and") { andor = andor; propertyname = propertyname; value = value; oper = oper; validateproperty(typeof(t), propertyname); } propertyinfo validateproperty(type type, string propertyname) { string[] parts = propertyname.split('.'); var info = (parts.length > 1) ? validateproperty(type.getproperty(parts[0]).propertytype, parts.skip(1).aggregate((a, i) => + "." + i)) : type.getproperty(propertyname); if (info == null) throw new argumentexception(propertyname, string.format("property {0} not member of {1}", propertyname, type.name)); return info; } } private expression getexpression(parameterexpression parameter, expressioncriterion expressioncriteria) { expression expression = parameter; foreach (var member in expressioncriteria.propertyname.split('.')) { expression = expression.propertyorfield(expression, member); } return expression.makebinary(expressioncriteria.oper, expression, expression.constant(expressioncriteria.value)); } public expression<func<t, bool>> getlambda() { expression expression = null; var parameterexpression = expression.parameter(typeof(t), typeof(t).name.tolower()); foreach (var item in _expressioncriterion) { if (expression == null) expression = getexpression(parameterexpression, item); else expression = item.andor == "and" ? expression.and(expression, getexpression(parameterexpression, item)) : expression.or(expression, getexpression(parameterexpression, item)); } return expression != null ? expression.lambda<func<t, bool>>(expression, parameterexpression) : null; } }
Comments
Post a Comment