> I am seeing another strange problem. I have an expression that looks like:
>
> (sb, name) => sb.Length > 0 ? sb.Append(", ").Append(name) : sb.Append(name)
>
> Unfortunately, by the time it gets to the AggregateBySeed, the
> expression looks something like:
>
> sb => sb.Length > 0 ? sb.Append(", ").Append([100001].name) :
> sb.Append([100001].name))
>
> I haven't had time to analyze why "name" was eaten, but I wonder if
> the new operators have an undetected relinq bug.
The "[100001]" expression is a reference to the query source whose
"name" property is aggregated. (If you use the
FormattingExpressionTreeVisitor.Format method instead of
Expression.ToString(), you'll see a more sensible expression.)
Here's an example:
(from o in Orders select o.Name).Aggregate (new StringBuilder(), (sb,
name) => sb.Length > 0 ? sb.Append(", ").Append(name) :
sb.Append(name))
This becomes the following QueryModel:
MainFromClause: from o in Orders
SelectClause: select [o].Name
AggregateFromSeedResultOperator:
Seed = new StringBuilder()
Func = sb => sb.Length > 0 ? sb.Append(", ").Append([o].name) :
sb.Append([o].name)
("[o]" denotes a reference to the query source "o", ie., a
QuerySourceReferenceExpression pointing to the MainFromClause.)
This is what re-linq always does when analyzing query operator
methods: it deduces what the input of the query operator actually
constitutes, and then puts a "resolved" expression into the result
operator.
In a LINQ provider, you usually have a mapping from IQuerySource
instances (eg., the MainFromClause) to something that describes the
data source in your target query system. In your case, this would
probably be the HQL AST node that represents the respective HQL "from"
clause. I'm quite sure that you already have that mapping because you
also need it to, eg., translate the QueryModel's "select" expression.
Use it to translate the result operator's Func to HQL.
If, for some reason, you cannot use that mapping, you can
reverse-resolve the expression. Check out the source code of
ExecuteInMemory[1] or contact me at
"http://groups.google.com/group/re-motion-users" if you need info on
how to do this.
Fabian
[1]
"https://svn.re-motion.org/svn/Remotion/trunk/Remotion/Data/Linq/Clauses/ResultOperators/AggregateFromSeedResultOperator.cs"
> On Tue, Feb 8, 2011 at 4:16 AM, Fabian Schmied <[email protected]>
> wrote:
>> This is a guess without seeing any of the exceptions:
>>
>> You (ie., some committer to NH) probably worked around a missing expression
>> parser for Queryable.Aggregate in a previous version of re-linq by handling
>> the respective MethodCallExpressions in an expression visitor. In the
>> current version, re-linq now recognizes the Aggregate methods as query
>> operators and converts them into
>> AggregateResultOperator/AggregateFromSeedResultOperator instances (similar
>> to what it does for all query operators).
>>
>> This means the code previously handling the MethodCallExpressions for
>> Queryable.Aggregate should now be rewritten to handle the result operators
>> instead.
>>
>> In general, whenever you have a query operator that's not detected by
>> re-linq, please don't write code handling the MethodCallExpressions
>> directly, but instead add an expression parser (IExpressionNode
>> implementation) for that method. This approach has several advantages, among
>> others that you avoid breaking your code with later versions of re-linq. See
>> my blog post
>> (https://www.re-motion.org/blogs/mix/archive/2010/10/28/re-linq-extensibility-custom-query-operators.aspx),
>> and post to the re-motion-users mailing list if there are any
>> questions/problems (or if re-linq is missing a standard query operator).
>>
>> (Out of curiosity: If I'm guessing correctly, _how_ do you actually
>> translate the Aggregate query operator to HQL? After all, the aggregation
>> function could contain completely arbitrary code...)
>>
>> Regards,
>> Fabian
>