Grouping Exception Object reference not set to an instance of an object

Posts   
 
    
mohamed avatar
mohamed
User
Posts: 136
Joined: 10-Mar-2008
# Posted on: 29-Jan-2009 14:09:19   

Greeting,

when executing this query by LINQ it through Exception Object reference not set to an instance of an object


select T1.EmpID,T2.EmpID,suM(T1.salary),sum(T2.Loan)
from T1 inner join T2 
    on t1.empID=t2.empID

group by T1.EmpID,T2.EmpID

this is LINQ


var xx = from t in metaData.T1
                     join t0 in metaData.T2 on t.EmpID equals t0.EmpID
                     group new { t, t0 } by new { t.EmpID, C1 = t0.EmpID } into g
                     select new
                        {
                            EmpID = g.Key.EmpID,
                            Column2 = g.Sum(p => p.t.Salary),
                            Column3 = g.Sum(p => p.t0.Loan)
                        };
var data = xx.ToList(); // Exception 

Exception Detail


System.NullReferenceException was unhandled
  Message="Object reference not set to an instance of an object."
  Source="SD.LLBLGen.Pro.LinqSupportClasses.NET35"
  StackTrace:
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleAggregateExpressionReferencingGroupBy(AggregateExpression expressionToHandle, Expression handledSource, QueryExpression handledSourceAsQuery, Expression handledArgument)
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleAggregateExpression(AggregateExpression expressionToHandle)
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle)
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleExpression(Expression expressionToHandle)
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleNewExpression(NewExpression expressionToHandle)
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle)
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleExpression(Expression expressionToHandle)
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleProjectionExpression(ProjectionExpression expressionToHandle)
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle)
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleExpression(Expression expressionToHandle)
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleSelectExpression(SelectExpression expressionToHandle, SelectExpression newInstance)
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleSelectExpression(SelectExpression expressionToHandle)
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleSelectExpression(SelectExpression expressionToHandle)
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle)
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleExpression(Expression expressionToHandle)
       at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.HandleExpressionTree(Expression expression)
       at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.Execute(Expression expression)
       at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.System.Linq.IQueryProvider.Execute(Expression expression)
       at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProQuery`1.Execute()
       at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
       at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
       at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
       at test.BL.Individual.GetData() in C:\Test\Test.BL\Individual.cs:line 49
       at Test.Win.Form1.button2_Click(Object sender, EventArgs e) in C:\Test\Test.Win\Form1.cs:line 63
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at Test.Win.Program.Main() in C:\Test\Test.Win\Program.cs:line 17
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 


runtime version data 21-1-2009 LLBL version 2.6 Adapter Using c# 3.5

mohamed avatar
mohamed
User
Posts: 136
Joined: 10-Mar-2008
# Posted on: 29-Jan-2009 15:25:49   

Now i change it to



                //select a.EmpID,a.salary,b.loan
                //from(
                //select T1.EmpID as EmpID,suM(T1.salary) as salary
                //from T1 
                //group by T1.EmpID) a
                //inner join (select T2.EmpID as EmpID,suM(T2.loan) as loan
                //from T2 
                //group by T2.EmpID) b

                //on a.EmpID=b.EmpID



            var aa = from a in
                         (
                             (from t in metaData.T1
                              group t by new{t.EmpID} into g
                              select new
                                 {
                                     EmpID = (System.Int32?) g.Key.EmpID,
                                     salary = g.Sum(p => p.Salary)
                                 }))
                     join b in
                         (
                             (from t in metaData.T2
                              group t by new{t.EmpID} into g
                                  select new
                                     {
                                         EmpID = (System.Int32?) g.Key.EmpID,
                                         loan = g.Sum(p => p.Loan)
                                     })) on a.EmpID equals b.EmpID
                     select new
                                {
                                    EmpID = (System.Int32?) a.EmpID,
                                    a.salary,
                                    b.loan
                                };

and its worked

but why doesn't previous query work ??flushed

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39859
Joined: 17-Aug-2003
# Posted on: 29-Jan-2009 16:13:51   

Not sure, I'll try to reproduce it.

(edit) I think I know what's the cause: the grouping in your initial query is between entities into an anonymous type. I fear this particular case has no code path. I'll see if I can add that. (as I see it's not a situation we thought of when writing the linq provider). The main reason for that is I think that the new {t, t0} set to group on is actually the join again but it's not inside the expression tree as a reference to the join. So the set to group on (new {t, t0} ) is something which is in-scope but not referred to as the join.

The main problem now is that in the expression tree the fields to aggregate are referring to the join'ed set (as linq is a pipeline, so every operator operates on the result of the previous operator), so the original table these fields are in is unknown. I used a trick to get this info by looking at the groupby's selection lambda, which contains the source to group and used the alias of that source (as it's the same source the aggregate works on). However, with your query, that's not going to work.

I tried linq to sql, it does figure out the right table to pull the aggregate field from but I have no idea how to do that. disappointed (there's no documentation whatsoever about this from MS). The main problem is that the source of the aggregate function in the linq query is the group by result and the source of the groupby is the joined set. Nowhere is it possible to obtain the REAL source of the aggregated field, at least I haven't found one other than the trick I described above (which fails in your case).

I'll see if I can still pull this info, but it's not the first time this problem has been challenged (last time we found the trick with the grouped source), so I have little hope I find something, although it should be possible as linq to sql can do it (but I don;t know how it obtains the necessary info).

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39859
Joined: 17-Aug-2003
# Posted on: 29-Jan-2009 18:41:25   

When I switch off the scoping of aliases inside the linq provider, it gives a proper query. Scoping is used to produce aliases which are inside a scope and not reachable outside the scope. For example: select * from (select a., b. from a join b on ...) c

here 'a' and 'b' are local aliases and not reachable for code outside the subquery, they should use 'c'. Here it's similar: an element refers to an element inside a scope (the join) and gets the alias of the join set, not the alias of the original element inside the join. The problem now is: when is the join a scope on its own for the elements referring to it, and when is it not a scope... I'll look into it.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39859
Joined: 17-Aug-2003
# Posted on: 30-Jan-2009 12:32:42   

Fixed in next build. It was a very nasty error: alias scoping is something which is necessary but there's no knowledge outside MS when and how to do this properly in all situations, so trial/error code is required. A problem is that at one point the logic has to make a decision in a narrow scope (e.g. handling of an aggregate function expression) which has influence on the handling of another part of the tree which seems unrelated (e.g. group by handling). Caused by the fact that group by statements on SQL are different than in Linq (and also why Linq's design is utterly flawed).

Anyway, I managed to add code which deals with this simple_smile

I'll correct the other issue you reported as well, so you'll see a new build attached to that thread.

Frans Bouma | Lead developer LLBLGen Pro
mohamed avatar
mohamed
User
Posts: 136
Joined: 10-Mar-2008
# Posted on: 01-Feb-2009 15:14:09   

Thanks Frans for getting solution, and for thinking aloud its worked perfectly thanks again simple_smile