PC Review


Reply
Thread Tools Rate Thread

Aggregation-Functions in an Expression Tree

 
 
Jan Rehm
Guest
Posts: n/a
 
      7th May 2009
Hello,
I'm currently trying to implement an extension of the DynamicQueryable class
in order to add aggregation functions (Sum, Min, Max, AVG).

The goal is to be able to use these functions to get a dynamically generated
SQL-Expression.

As the database is filled with "null" and "string", a Lambda-Expression is
needed to convert these values into a useable format.

Trial and error with static Linq-Queries have brought me to this query:

var query = dxStatic.T_OBJ11s.Sum(g => g.F13 == null ? 0 :
Convert.ToDouble(g.F13));

with dxStatic being a System.Data.Linq.DataContext to connect to the Database.

This query produces the expected values from the database.

Then, I tried to translate this query into an ExpressionTree, in order to be
able to further refine/change the query during runtime.

This is where I hit a snag:

Creating the Lambda-Expression was comparatively easy:

private static LambdaExpression ConvertTable(IQueryable source, string key)
{
// Source is once again Syste.Data.Linq.DataContext

// g
ParameterExpression TableObj =
Expression.Parameter(source.ElementType, "g");

// g.key
MemberInfo Key = source.ElementType.GetMember(key)[0];
MemberExpression Column = Expression.MakeMemberAccess(TableObj, Key);

// null, 0
ConstantExpression Null = Expression.Constant(null);
ConstantExpression Zero = Expression.Constant((decimal)0,
typeof(decimal));

// g.key == null
Expression query = Expression.Equal(Column, Null);

// Convert.ToDecimal(g.key)
MethodInfo ConverterMethod = typeof(Convert).GetMethod("ToDecimal",
new Type[] { typeof(string) });
Expression convert = Expression.Call(ConverterMethod, Column);

// g.key==null ? 0 : Convert.ToDecimal(g.key)
Expression decider = Expression.Condition(query, Zero, convert);

// g => (g.key==null ? 0 : Convert.ToDecimal(g.key))
LambdaExpression ConvertOrNull = Expression.Lambda(decider, TableObj);


return ConvertOrNull;
}


The LambdaExpression can then be used:

public static IQueryable Sum(this IQueryable source, string key, params
object[] values)
{
if (source == null) throw new ArgumentNullException("source");
if (key==null) throw new ArgumentNullException("key");

// g => (g.key==null ? 0 : Convert.ToDecimal(g.key))
LambdaExpression ConvertOrNull = ConvertTable(source, key);

Expression SumExpression = Expression.Call(typeof(Queryable), "Sum",
new Type[] { source.ElementType }, source.Expression,
Expression.Quote(ConvertOrNull));

return source.Provider.CreateQuery(SumExpression);
}

This fails, due to an error in CreateQuery. Further research with .NET
Reflector led to this:

Type type = TypeHelper.FindGenericType(typeof(IQueryable<>),
expression.Type);
if (type == null)
{
throw Error.ArgumentNotValid("expression");
}

As type is always null, FindGenericType obviously can't find a generic type.

I've tried a lot of different approaches to solve this Problem, but I'm
stumped. Can anybody help?

Thank you.

-Jan
 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
lambda expression with a statement body cannot be converted to anexpression tree Steve Richter Microsoft C# .NET 2 25th May 2009 01:56 AM
lambda expression with a statement body cannot be converted to anexpression tree Steve Richter Microsoft C# .NET 0 25th May 2009 01:12 AM
LINQ join using Expression Tree Darren Microsoft C# .NET 12 4th Dec 2008 08:54 PM
Expression using RIGHT and LEN functions =?Utf-8?B?TWFybGVuZQ==?= Microsoft Access Queries 2 22nd Feb 2005 12:48 AM
Functions --> Expression =?Utf-8?B?RGVyZWsgV2l0dG1hbg==?= Microsoft Access VBA Modules 7 29th Jan 2004 01:19 AM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 02:56 AM.