Difference between two date in minutes

Posts   
 
    
erakis
User
Posts: 24
Joined: 17-Jan-2012
# Posted on: 23-Jan-2012 18:15:22   

Hi,

I would like to compute a time sheet for a user but I get the following error :

Aggregate function can't be applied as it's not possible to find a field to apply the aggregate on

First of all I'm using the latest version of LLBLGen (download today). .NET 3.5 and SQL Server Express 2008

Here is the tables involved in the query :


Employes
{
   EmployesCode   INT
   FirstName      NVARCHAR(150)
   LastName   NVARCHAR(150)
}

EmployesTimeSheet
{
   EmployesCode   INT
   timeStart      DATETIME NOT NULL
   timeEnd      DATETIME NULL
}

And now the LINQ query


var query = (from q in lmd.Employes
             join tEmployesTimeSheet in lmd.EmployesTimeSheet on new { q.EmployesCode } equals new { tEmployesTimeSheet.EmployesCode } into groupJoinEmployesTimeSheet
             from gEmployesTimeSheet in groupJoinEmployesTimeSheet.DefaultIfEmpty()

             group new { q, tEmployesTimeSheet } by new
             {
                  q.EmployesCode,
                  q.FirstName,
                  q.LastName
              } into g
              select new
              {
                  g.Key.EmployesCode,
                  g.Key.FirstName,
                  g.Key.LastName,
                  EmployesTotalMinutesTimeSheet = g.Sum(p => p.gEmployesTimeSheet.timeEnd.Value - p.gEmployesTimeSheet.timeStart).TotalMinutes)
              }).ToList();

Here is the stack trace for reference


SD.LLBLGen.Pro.ORMSupportClasses.ORMQueryConstructionException was unhandled
  Message="Aggregate function can't be applied as it's not possible to find a field to apply the aggregate on"
  Source="SD.LLBLGen.Pro.LinqSupportClasses.NET35"
  RuntimeBuild="11292011"
  RuntimeVersion="3.1.0.0"
  StackTrace:
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleAggregateExpressionReferencingGroupBy(AggregateExpression expressionToHandle, Expression handledSource, QueryExpression handledSourceAsQuery, Expression handledArgument, Expression handledElementSelector) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\ExpressionHandlers\QueryExpressionBuilder.cs:line 492
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleAggregateExpression(AggregateExpression expressionToHandle) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\ExpressionHandlers\QueryExpressionBuilder.cs:line 345
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\ExpressionHandlers\GenericExpressionHandler.cs:line 136
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleExpression(Expression expressionToHandle) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\ExpressionHandlers\QueryExpressionBuilder.cs:line 141
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleCtorOrMemberAssignmentParameter(Expression expression) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\ExpressionHandlers\QueryExpressionBuilder.cs:line 4249
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleNewExpression(NewExpression expressionToHandle) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\ExpressionHandlers\QueryExpressionBuilder.cs:line 2454
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\ExpressionHandlers\GenericExpressionHandler.cs:line 299
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleExpression(Expression expressionToHandle) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\ExpressionHandlers\QueryExpressionBuilder.cs:line 141
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleProjectionExpression(ProjectionExpression expressionToHandle) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\ExpressionHandlers\QueryExpressionBuilder.cs:line 2622
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\ExpressionHandlers\GenericExpressionHandler.cs:line 201
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleExpression(Expression expressionToHandle) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\ExpressionHandlers\QueryExpressionBuilder.cs:line 141
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleSelectExpression(SelectExpression expressionToHandle, SelectExpression newInstance) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\ExpressionHandlers\GenericExpressionHandler.cs:line 818
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleSelectExpression(SelectExpression expressionToHandle) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\ExpressionHandlers\GenericExpressionHandler.cs:line 796
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleSelectExpression(SelectExpression expressionToHandle) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\ExpressionHandlers\QueryExpressionBuilder.cs:line 3154
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\ExpressionHandlers\GenericExpressionHandler.cs:line 207
       at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleExpression(Expression expressionToHandle) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\ExpressionHandlers\QueryExpressionBuilder.cs:line 141
       at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.HandleExpressionTree(Expression expression) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\LLBLGenProProviderBase.cs:line 158
       at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.Execute(Expression expression) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\LLBLGenProProviderBase.cs:line 92
       at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.System.Linq.IQueryProvider.Execute(Expression expression) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\LLBLGenProProviderBase.cs:line 697
       at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProQuery`1.Execute() in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\LLBLGenProQuery.cs:line 87
       at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.1\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\LLBLGenProQuery.cs:line 162
       at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
       at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
       at TestProject.Form1.Form1_Load(Object sender, EventArgs e) in D:\LLBLGenCTAQManager\TestProject\TestProject\TestProject\Form1.cs:line 408
       at System.Windows.Forms.Form.OnLoad(EventArgs e)
       at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
       at System.Windows.Forms.Control.CreateControl()
       at System.Windows.Forms.Control.WmShowWindow(Message& m)
       at System.Windows.Forms.Control.WndProc(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)
  InnerException: 

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 24-Jan-2012 04:52:19   

Mmm. there are some things to note about your query:

  1. It seems that you have an extra ")" that shouln't be there. Please double check that.

  2. There is no a function mapping that would work on (someDate - someDate) or Substract. Then there is no function mapping that would return a TotalMinutes. Read here to know the supported built-in Linq function mappings. So you have to write your own function mapping. Example:

public class MyDBFunctions
{       
    public static int DateDiffInMinutes(DateTime dateStart, DateTime dateEnd)
    {
        return 0;
    }
}


public class MyDBFunctionMappings : FunctionMappingStore
{
    public MyDBFunctionMappings ()
        : base()
    {       
        this.Add(new FunctionMapping(typeof(MyDBFunctions), "DateDiffInMinutes", 2, "DATEDIFF(minute, {0}, {1})"));
    }
}

.. then in your code (I reformatted it a little bit):

lmd.CustomFunctionMappings = new MyDBFunctionMappings();
var query = 
    (
        from q in lmd.Employes
        join tEmployesTimeSheet in lmd.EmployesTimeSheet on q.EmployesCode equals tEmployesTimeSheet.EmployesCode 
             into groupJoinEmployesTimeSheet
        from gEmployesTimeSheet in groupJoinEmployesTimeSheet.DefaultIfEmpty()

        group new { q, tEmployesTimeSheet } by new
        {
            q.EmployesCode,
            q.FirstName,
            q.LastName
        } into g

        select new
        {
            g.Key.EmployesCode,
            g.Key.FirstName,
            g.Key.LastName,
            EmployesTotalMinutesTimeSheet = 
                 g.Sum(p => MyDBFunctions.DateDiffInMinutes(p.gEmployesTimeSheet.timeEnd.Value, p.gEmployesTimeSheet.timeStart))
        }).ToList();

Hope helpful wink

David Elizondo | LLBLGen Support Team
erakis
User
Posts: 24
Joined: 17-Jan-2012
# Posted on: 24-Jan-2012 14:10:37   

Thanks daelmo for your help wink

Now I see why the time operation was not working. The last extra ")" was a typo error, sorry.

I want to be as flexible as possible, so that my system can run on MS SQL Server, MySQL and MS Access for the worst.

If I write my own mapping function I loose this compatibility.

In conclusion, do you plan shortly supporting more timepsan and date operation ?

Best regards, Martin

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 24-Jan-2012 19:15:57   

erakis wrote:

I want to be as flexible as possible, so that my system can run on MS SQL Server, MySQL and MS Access for the worst.

If I write my own mapping function I loose this compatibility.

I understand what you mean. But you can overcome this. You can write this code in your DBGeneric project:

public class MyDBFunctions
{       
    public static int DateDiffInMinutes(DateTime dateStart, DateTime dateEnd)
    {
        return 0;
    }
}

and this one in your DBSpecific project:

public class MyDBFunctionMappings : FunctionMappingStore
{
    public MyDBFunctionMappings ()
        : base()
    {       
        this.Add(new FunctionMapping(typeof(MyDBFunctions), "DateDiffInMinutes", 2, "DATEDIFF(minute, {0}, {1})"));
    }
}

Now you don't have that problem. If you change the target database, say from SQLServer to MySql then you need to generate another DBSpecific project, thus the MyDBFunctionMappings class as well, f.i.:

public class MyDBFunctionMappings : FunctionMappingStore
{
    public MyDBFunctionMappings ()
        : base()
    {       
        this.Add(new FunctionMapping(typeof(MyDBFunctions), "DateDiffInMinutes", 2, "MINUTE(DATEDIFF({0}, {1}))"));
    }
}

The DBGeneric code and your other projects remain the same, you just need to specialize the DBSpecifi project depending upon the target DB. You need to do this anyway if you have custom database functions.

erakis wrote:

In conclusion, do you plan shortly supporting more timepsan and date operation ?

I will see if there is any plans to increase the supported function mappings for LINQ2LLBL. What I guess is that there will be always some not supported functions you will have to map yourself.

David Elizondo | LLBLGen Support Team
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39908
Joined: 17-Aug-2003
# Posted on: 25-Jan-2012 10:11:46   

For now there are no plans to extend the function mappings, as the ones we have are the most common ones and if you need a custom one, you can add it with a few lines with code which is located in your own project.

Frans Bouma | Lead developer LLBLGen Pro