- Home
- LLBLGen Pro
- LLBLGen Pro Runtime Framework
Join with DatePart
Joined: 20-Apr-2006
I am having an issue grouping a table by Date. I am trying to get all the activity for a particular UserId based on the Date it was entered.
CREATE TABLE [dbo].[custActivity](
[ActivityId] [int] IDENTITY(1,1) NOT NULL,
[CustomerId] [int] NOT NULL,
[UserId] [uniqueidentifier] NOT NULL,
[User] [nvarchar](100) NOT NULL,
[ActivityType] [nvarchar](50) NOT NULL,
[Message] [nvarchar](300) NOT NULL,
[ActivityDate] [datetime] NOT NULL CONSTRAINT [DF_custActivity_ActivityDate]
var activity = (from t in db.CustActivity
where t.UserId == userId
group t by new { t.ActivityDate.Day, t.ActivityDate.Month, t.ActivityDate.Year } into g
select new BusinessEntities.Activity.List {
Date = new DateTime(g.Key.Year, g.Key.Month, g.Key.Day),
Activity = (from a in db.CustActivity
where a.ActivityDate.Date == new DateTime(g.Key.Year, g.Key.Month, g.Key.Day)
select new BusinessEntities.Customer.Activity {
CustomerId = a.CustomerId,
Message = a.Message,
Type = a.ActivityType.EnumParse<BusinessEntities.Customer.ActivityType>(true),
User = a.User,
UserId = a.UserId,
Date = a.ActivityDate
}).ToList()
}).ToList();
I get the following error and stack trace.
RuntimeBuild="08042008" Message="The binary expression '([505] = new DateTime([513].Year, [513].Month, [513].Day))' can't be converted to a predicate expression."
SD.LLBLGen.Pro.ORMSupportClasses.ORMQueryConstructionException was unhandled by user code
Message="The binary expression '([505] = new DateTime([513].Year, [513].Month, [513].Day))' can't be converted to a predicate expression."
Source="SD.LLBLGen.Pro.LinqSupportClasses.NET35"
RuntimeBuild="08042008"
RuntimeVersion="2.6.0.0"
StackTrace:
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleBinaryExpressionSeparateOperands(BinaryExpression expressionToHandle, Expression leftSide, Expression rightSide)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleBinaryExpressionBooleanOperator(BinaryExpression 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.HandleLambdaExpression(LambdaExpression 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.HandleWhereExpression(WhereExpression 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.ExpressionHandlers.GenericExpressionHandler.HandleExpressionList(ReadOnlyCollection`1 listToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleMethodCallExpression(MethodCallExpression expressionToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleMethodCallExpression(MethodCallExpression 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.HandleMemberAssignment(MemberAssignment assignmentToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleMemberBinding(MemberBinding bindingToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleMemberBindingList(ReadOnlyCollection`1 listToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleMemberInitExpression(MemberInitExpression 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 LenderFlex.WebConnect.Client.DataAccess.CustomerRepository.UserActivityGet(Guid userId) in C:\Projects\Project\Source\Resource Access\Project.Client.DataAccess\CustomerRepository.cs:line 800
at Project.BusinessLogic.Managers.Customer.ActivityManager.UserCustomerActivityGet(Guid userId) in C:\Projects\Project\Source\Business Logic\Project.BusinessLogic\Managers\Customer\ActivityManager.cs:line 37
at Project.Default.Page_Load(Object sender, EventArgs e) in C:\Projects\Project\Source\Host\Project\Default.aspx.cs:line 26
at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
at System.Web.UI.Control.OnLoad(EventArgs e)
at Project.BasePage.OnLoad(EventArgs e) in C:\Projects\Project\Source\Host\Project\BasePage.cs:line 159
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
InnerException:
Also, I ended up using the DatePart method becuase I couldn't get the DateTime.Date conversion to work. This does work in Linq to SQL but not in the LLBL Gen implementation.
var a1 = (from t in db.CustActivity
where t.UserId == userId
group t by t.ActivityDate.Date into g
select new BusinessEntities.Activity.List {
Date = g.Key
}).ToList();
jgombala wrote:
var a1 = (from t in db.CustActivity where t.UserId == userId group t by t.ActivityDate.Date into g select new BusinessEntities.Activity.List { Date = g.Key }).ToList();
Try this:
var q = from t in db.CustActivity
where t.UserId == userId
select new {t.ActivityDate.Value.Date} into ad
group ad by ad.Date into g
select new { TheDate = g.Key };
You get the error here: where a.ActivityDate.Date == new DateTime(g.Key.Year, g.Key.Month, g.Key.Day)
and this is because the dateTime CTor isn't mapped onto a DB construct, so it's not convertable to something that's usable inside the DB. You can add a mapping yourself (see Functionmappings in the Linq section of the manual), though I think it's perhaps also possible to rewrite the query.
Keep in mind that these kind of constructions aren't always convertable to SQL, because you're using in-memory code.
What error did you get with this query:
var a1 = (from t in db.CustActivity
where t.UserId == userId
group t by t.ActivityDate.Date into g
select new BusinessEntities.Activity.List {
Date = g.Key
}).ToList();
?
Joined: 20-Apr-2006
daelmo wrote:
Try this:
var q = from t in db.CustActivity where t.UserId == userId select new {t.ActivityDate.Value.Date} into ad group ad by ad.Date into g select new { TheDate = g.Key };
I get a notification that System.DateTime does not contain a definition for 'Value'... The only time I was able to use 'Value' was when I had the DB column set to nullable. Even then it still would throw an error.
jgombala wrote:
daelmo wrote:
Try this:
var q = from t in db.CustActivity where t.UserId == userId select new {t.ActivityDate.Value.Date} into ad group ad by ad.Date into g select new { TheDate = g.Key };
I get a notification that System.DateTime does not contain a definition for 'Value'... The only time I was able to use 'Value' was when I had the DB column set to nullable. Even then it still would throw an error.
Erm... t.ActivityDate is of type DateTime I pressume? As it's not nullable, and DateTime doesn't have a 'Value' property, what's '.Value' in the query above?
Joined: 20-Apr-2006
Otis wrote:
You get the error here: where a.ActivityDate.Date == new DateTime(g.Key.Year, g.Key.Month, g.Key.Day)
and this is because the dateTime CTor isn't mapped onto a DB construct ... though I think it's perhaps also possible to rewrite the query.
Any insight on how to rewrite the query? I've tried everything that I know of.
The following query throws an error: A nested query in the projection has no correlation filter to tie its set to the containing parent row. Please add a correlation filter to the where clause of this query to tie the nested query to the parent.
I am not sure how correlate the nested query when the group by is multiple keys.
var activity = (from t in db.CustActivity
where t.UserId == userId
group t by new { t.ActivityDate.Day, t.ActivityDate.Month, t.ActivityDate.Year } into g
select new BusinessEntities.Activity.List {
Date = new DateTime(g.Key.Year, g.Key.Month, g.Key.Day),
Activity = (from a in db.CustActivity
where a.ActivityDate.Date.Year == g.Key.Year
where a.ActivityDate.Month == g.Key.Month
where a.ActivityDate.Day == g.Key.Day
select new BusinessEntities.Customer.Activity {
CustomerId = a.CustomerId,
...
}).ToList()
}).ToList();
Stack Trace:
StackTrace:
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionClasses.QueryExpression.FindCorrelationFilterPredicates(IElementCreatorCore generatedCodeElementCreator)
at SD.LLBLGen.Pro.LinqSupportClasses.ValueListProjectionDefinition.AddNestedQueryToProjection(QueryExpression nestedQuery, String elementName, Type elementType, Boolean addConstantHandlerToProjection, ITemplateGroupSpecificCreator frameworkElementCreator, IElementCreatorCore generatedCodeElementCreator)
at SD.LLBLGen.Pro.LinqSupportClasses.ValueListProjectionDefinition.AddProjectionListToProjection(ProjectionListExpression toAdd, ITemplateGroupSpecificCreator frameworkElementCreator, IElementCreatorCore generatedCodeElementCreator)
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()
Otis wrote:
What error did you get with this query:
var a1 = (from t in db.CustActivity where t.UserId == userId group t by t.ActivityDate.Date into g select new BusinessEntities.Activity.List { Date = g.Key }).ToList();
?
I get "Value cannot be null.\r\nParameter name: expression"
System.ArgumentNullException was unhandled by user code
Message="Value cannot be null.\r\nParameter name: expression"
Source="System.Core"
ParamName="expression"
StackTrace:
at System.Linq.Expressions.Expression.Bind(MemberInfo member, Expression expression)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleMemberAssignment(MemberAssignment assignmentToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleMemberBinding(MemberBinding bindingToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleMemberBindingList(ReadOnlyCollection`1 listToHandle)
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleMemberInitExpression(MemberInitExpression 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 Project.Client.DataAccess.CustomerRepository.UserActivityGet(Guid userId) in C:\Projects\Project\Source\Resource Access\Project.Client.DataAccess\CustomerRepository.cs:line 801
at Project.BusinessLogic.Managers.Customer.ActivityManager.UserCustomerActivityGet(Guid userId) in C:\Projects\Project\Source\Business Logic\Project.BusinessLogic\Managers\Customer\ActivityManager.cs:line 37
at Project.Default.Page_Load(Object sender, EventArgs e) in C:\Projects\Project\Source\Host\Project\Default.aspx.cs:line 26
at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
at System.Web.UI.Control.OnLoad(EventArgs e)
at Project.BasePage.OnLoad(EventArgs e) in C:\Projects\Project\Source\Host\Project\BasePage.cs:line 159
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
InnerException:
jgombala wrote:
Otis wrote:
You get the error here: where a.ActivityDate.Date == new DateTime(g.Key.Year, g.Key.Month, g.Key.Day)
and this is because the dateTime CTor isn't mapped onto a DB construct ... though I think it's perhaps also possible to rewrite the query.
Any insight on how to rewrite the query? I've tried everything that I know of.
The following query throws an error: A nested query in the projection has no correlation filter to tie its set to the containing parent row. Please add a correlation filter to the where clause of this query to tie the nested query to the parent.
I am not sure how correlate the nested query when the group by is multiple keys.
var activity = (from t in db.CustActivity where t.UserId == userId group t by new { t.ActivityDate.Day, t.ActivityDate.Month, t.ActivityDate.Year } into g select new BusinessEntities.Activity.List { Date = new DateTime(g.Key.Year, g.Key.Month, g.Key.Day), Activity = (from a in db.CustActivity where a.ActivityDate.Date.Year == g.Key.Year where a.ActivityDate.Month == g.Key.Month where a.ActivityDate.Day == g.Key.Day select new BusinessEntities.Customer.Activity { CustomerId = a.CustomerId, ... }).ToList() }).ToList();
This error occurs due to the nested subquery in the projection: as it is executed separately, it has to know how to relate rows produced by that nested query to the rows in the outer query.
You pass in the key of the group by, the code overlooks that as it only works with field compares at this stage because the groupby key isn't in the projection of the outer query, it can't make this workable: how to compare a row in the outer set to a row in the inner set?
Creating efficient nested queries is a complex issue, and therefore we first supported nested queries with normal field - field comparison correlation filters, as the rest is very complex to do (if not impossible, as the correlation you specify above is undoable in a query as the values to compare with aren't in the projection of the outer query).
I also asked a question about 'Value', you ignored it, though it's key that you are consistent towards us what you're testing and what goes wrong exactly. we don't have the code you 're using in front of us, so all we have is what you post here. The query above in the previous post with '.Value' on the datetime field is confusing.
Otis wrote:
What error did you get with this query:
var a1 = (from t in db.CustActivity where t.UserId == userId group t by t.ActivityDate.Date into g select new BusinessEntities.Activity.List { Date = g.Key }).ToList();
?
I get "Value cannot be null.\r\nParameter name: expression"
Will look into it. Though I think it's the DB function construct executed for 'Date'.
Btw, your initial quest: "I am trying to get all the activity for a particular UserId based on the Date it was entered." Is that: filtered on a particular date, or grouped by date?
I can reproduce the error you got, looking into it.
(edit) the g.Key reference in the projection is a dbfunction call (as the .Date property requires a db construction of several functions to work) and that's not expected, working on fixing this. There's another issue I ran into, (probably related) I'll fix that too.
Joined: 20-Apr-2006
Otis wrote:
This error occurs due to the nested subquery in the projection: as it is executed separately, it has to know how to relate rows produced by that nested query to the rows in the outer query.
You pass in the key of the group by, the code overlooks that as it only works with field compares at this stage because the groupby key isn't in the projection of the outer query, it can't make this workable: how to compare a row in the outer set to a row in the inner set?
Creating efficient nested queries is a complex issue, and therefore we first supported nested queries with normal field - field comparison correlation filters, as the rest is very complex to do (if not impossible, as the correlation you specify above is undoable in a query as the values to compare with aren't in the projection of the outer query).
Understood and makes sense. I would, however, assume you would compare the outer set to the inner set on the grouped by date. I am, just for the record, able to take the same query and run it in LINQPad with out any issues. What it appears is that the Linq To SQL implementation is taking the "where a.ActivityDate.Date == new DateTime(g.Key.Year, g.Key.Month, g.Key.Day)" and converting it to SQL DatePart functions.
LINQPad generates the following SQL for the same Linq code I posted...
SELECT CONVERT(DATETIME, CONVERT(NCHAR(2), [t2].[value2]) + ('/' + (CONVERT(NCHAR(2), [t2].[value]) + ('/' + CONVERT(NCHAR(4), [t2].[value3])))), 101) AS [Date], [t2].[value2], [t2].[value], [t2].[value3]
FROM (
SELECT [t1].[value], [t1].[value2], [t1].[value3]
FROM (
SELECT DATEPART(Day, [t0].[ActivityDate]) AS [value], DATEPART(Month, [t0].[ActivityDate]) AS [value2], DATEPART(Year, [t0].[ActivityDate]) AS [value3]
FROM [custActivity] AS [t0]
) AS [t1]
GROUP BY [t1].[value], [t1].[value2], [t1].[value3]
) AS [t2]
ORDER BY [t2].[value3] DESC, [t2].[value2] DESC, [t2].[value] DESC
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30428.1
SELECT [t0].[CustomerId], [t0].[Message], [t0].[ActivityType] AS [Type], [t0].[User], [t0].[UserId], [t0].[ActivityDate] AS [Date]
FROM [custActivity] AS [t0]
WHERE DATEADD(HOUR, -DATEPART(HOUR, [t0].[ActivityDate]), DATEADD(MINUTE, -DATEPART(MINUTE, [t0].[ActivityDate]), DATEADD(SECOND, -DATEPART(SECOND, [t0].[ActivityDate]), DATEADD(MILLISECOND, -DATEPART(MILLISECOND, [t0].[ActivityDate]), [t0].[ActivityDate])))) = CONVERT(DATETIME, CONVERT(NCHAR(2), @x1) + ('/' + (CONVERT(NCHAR(2), @x2) + ('/' + CONVERT(NCHAR(4), @x3)))), 101)
-- @x1: Input Int (Size = 0; Prec = 0; Scale = 0) [8]
-- @x2: Input Int (Size = 0; Prec = 0; Scale = 0) [4]
-- @x3: Input Int (Size = 0; Prec = 0; Scale = 0) [2008]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30428.1
SELECT [t0].[CustomerId], [t0].[Message], [t0].[ActivityType] AS [Type], [t0].[User], [t0].[UserId], [t0].[ActivityDate] AS [Date]
FROM [custActivity] AS [t0]
WHERE DATEADD(HOUR, -DATEPART(HOUR, [t0].[ActivityDate]), DATEADD(MINUTE, -DATEPART(MINUTE, [t0].[ActivityDate]), DATEADD(SECOND, -DATEPART(SECOND, [t0].[ActivityDate]), DATEADD(MILLISECOND, -DATEPART(MILLISECOND, [t0].[ActivityDate]), [t0].[ActivityDate])))) = CONVERT(DATETIME, CONVERT(NCHAR(2), @x1) + ('/' + (CONVERT(NCHAR(2), @x2) + ('/' + CONVERT(NCHAR(4), @x3)))), 101)
-- @x1: Input Int (Size = 0; Prec = 0; Scale = 0) [8]
-- @x2: Input Int (Size = 0; Prec = 0; Scale = 0) [1]
-- @x3: Input Int (Size = 0; Prec = 0; Scale = 0) [2008]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30428.1
SELECT [t0].[CustomerId], [t0].[Message], [t0].[ActivityType] AS [Type], [t0].[User], [t0].[UserId], [t0].[ActivityDate] AS [Date]
FROM [custActivity] AS [t0]
WHERE DATEADD(HOUR, -DATEPART(HOUR, [t0].[ActivityDate]), DATEADD(MINUTE, -DATEPART(MINUTE, [t0].[ActivityDate]), DATEADD(SECOND, -DATEPART(SECOND, [t0].[ActivityDate]), DATEADD(MILLISECOND, -DATEPART(MILLISECOND, [t0].[ActivityDate]), [t0].[ActivityDate])))) = CONVERT(DATETIME, CONVERT(NCHAR(2), @x1) + ('/' + (CONVERT(NCHAR(2), @x2) + ('/' + CONVERT(NCHAR(4), @x3)))), 101)
-- @x1: Input Int (Size = 0; Prec = 0; Scale = 0) [7]
-- @x2: Input Int (Size = 0; Prec = 0; Scale = 0) [31]
-- @x3: Input Int (Size = 0; Prec = 0; Scale = 0) [2008]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30428.1
Otis wrote:
I also asked a question about 'Value', you ignored it, though it's key that you are consistent towards us what you're testing and what goes wrong exactly. we don't have the code you 're using in front of us, so all we have is what you post here. The query above in the previous post with '.Value' on the datetime field is confusing.
Wasn't ignoring it... I didn't use 'Value'. That was a suggestion from someone else in this post [daelmo] that I try that to fix my issue. You'll see in all the queries I posted that 'Value' wasn't specified.
Otis wrote:
Btw, your initial quest: "I am trying to get all the activity for a particular UserId based on the Date it was entered." Is that: filtered on a particular date, or grouped by date?
Grouped by the Activity Date for a particular UserId. Not for a particular date.
jgombala wrote:
Otis wrote:
This error occurs due to the nested subquery in the projection: as it is executed separately, it has to know how to relate rows produced by that nested query to the rows in the outer query.
You pass in the key of the group by, the code overlooks that as it only works with field compares at this stage because the groupby key isn't in the projection of the outer query, it can't make this workable: how to compare a row in the outer set to a row in the inner set?
Creating efficient nested queries is a complex issue, and therefore we first supported nested queries with normal field - field comparison correlation filters, as the rest is very complex to do (if not impossible, as the correlation you specify above is undoable in a query as the values to compare with aren't in the projection of the outer query).
Understood and makes sense. I would, however, assume you would compare the outer set to the inner set on the grouped by date. I am, just for the record, able to take the same query and run it in LINQPad with out any issues. What it appears is that the Linq To SQL implementation is taking the "where a.ActivityDate.Date == new DateTime(g.Key.Year, g.Key.Month, g.Key.Day)" and converting it to SQL DatePart functions.
The main difference is that Linq to Sql doesn't do any nested query logic. It simply executes for every row in the resultset, the nested query again, so if your outer query results in 1000 rows, it will run 1000 times the nested query. As you can see, with 3 rows in the outer query, it will run the nested query 3 times.
We didn't opt for this scenario as it's incredibly inefficient, and it requires a lot of extra code in the provider (and generated IL classes have to be able to execute queries on the fly).
Otis wrote:
I also asked a question about 'Value', you ignored it, though it's key that you are consistent towards us what you're testing and what goes wrong exactly. we don't have the code you 're using in front of us, so all we have is what you post here. The query above in the previous post with '.Value' on the datetime field is confusing.
Wasn't ignoring it... I didn't use 'Value'. That was a suggestion from someone else in this post [daelmo] that I try that to fix my issue. You'll see in all the queries I posted that 'Value' wasn't specified.
Ah My appologies.
Otis wrote:
Btw, your initial quest: "I am trying to get all the activity for a particular UserId based on the Date it was entered." Is that: filtered on a particular date, or grouped by date?
Grouped by the Activity Date for a particular UserId. Not for a particular date.
Ok, understood. Indeed then the query makes perfect sense (the last one, the first one you posted is extremely complex and not necessary). I'll report back when I've done the necessary changes to make yuor query (and other similar constructs) work.
This one now works:
var q = from o in metaData.Order
where o.CustomerId == "CHOPS"
group o by o.OrderDate.Value.Date into g
select new { Date = g.Key };
this one still fails:
var q = from o in metaData.Order
where o.CustomerId == "CHOPS"
group o by o.OrderDate.Value into g
select g;
Ok that one now also works.
I've attached a new build. Could you try it out please? The query you should use is:
var a1 = (from t in db.CustActivity
where t.UserId == userId
group t by t.ActivityDate.Date into g
select g).ToList();
this gives a list of IGrouping<DateTime, CustActivityEntity> objects, so you have all your entities hierarchical grouped together by key.
(edit) Attachment pulled, still buggy.
Joined: 20-Apr-2006
var a1 = (from t in db.CustActivity
where t.UserId == userId
group t by t.ActivityDate.Date into g
select g).ToList();
Gives me an error of: "A nested query relies on a correlation filter which refers to the field 'LPFA_3', however this field wasn't found in the projection of the entity."
Even though I loaded the new DLL the runtime build number didn't change. It is still at "08042008"... is this correct or did the new DLL not load correctly?
Stack:
SD.LLBLGen.Pro.ORMSupportClasses.ORMQueryConstructionException was unhandled by user code
Message="A nested query relies on a correlation filter which refers to the field 'LPFA_3', however this field wasn't found in the projection of the entity."
Source="SD.LLBLGen.Pro.LinqSupportClasses.NET35"
RuntimeBuild="08042008"
RuntimeVersion="2.6.0.0"
StackTrace:
at SD.LLBLGen.Pro.LinqSupportClasses.LinqUtils.AddFieldToProjectionIfNotPresent(IEntityFieldCore fieldToCheck, ProjectionDefinition projection, IElementCreatorCore generatedCodeElementCreator)
at SD.LLBLGen.Pro.LinqSupportClasses.ValueListProjectionDefinition.PostProcessNestedQueries(ITemplateGroupSpecificCreator frameworkElementCreator, IElementCreatorCore generatedCodeElementCreator, MappingTracker trackedMappings)
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 Project.Client.DataAccess.CustomerRepository.UserActivityGet(Guid userId) in C:\Projects\Project\Source\Resource Access\Project.Client.DataAccess\CustomerRepository.cs:line 803
at Project.BusinessLogic.Managers.Customer.ActivityManager.UserCustomerActivityGet(Guid userId) in C:\Projects\Project\Source\Business Logic\Project.BusinessLogic\Managers\Customer\ActivityManager.cs:line 37
at Project.Default.Page_Load(Object sender, EventArgs e) in C:\Projects\Project\Source\Host\Project\Default.aspx.cs:line 26
at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
at System.Web.UI.Control.OnLoad(EventArgs e)
at Project.BasePage.OnLoad(EventArgs e) in C:\Projects\Project\Source\Host\Project\BasePage.cs:line 159
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
InnerException:
Arg.... I see, my test was wrong! What a blunder... .
You of course need the Date function call because you want to filter out the Time part of the values to group on...
Will look into this as well. Sorry for this inconvenience.
Joined: 20-Apr-2006
Thanks Otis.
No inconvenience at all. I actually have to pull my grouping logic out and do it in memory. I am doing some complex constructs and DateTime conversions...
But it will be nice to know that we will be able to do Linq queries based on datetime grouping. I am sure I will need this ability in the near future. I will be happy to continue testing...
As always, the service and response provided by you is top class.
Hmm, this is very tough to solve. The problem is the '.Date' property which is converted to a DB construct. '.Date' is an existing .NET property with actual code and meaning in memory. However you can map this Date property onto another db construct or use a .NET extension method on DateTime you wrote yourself and a custom mapping and group with that. This will give a grouped set with the key values returned. However, to merge the two sets in memory, the group by key lambda has to be applied on each entity returned, in memory. This will give different results, in the case where you used a custom mapping and probably different results if you used the default mapping but where tiny differences are present between DB execution/function and in-memory function.
The query processing now goes wrong where it has to build a pair of fields to compare between outer and inner query, and the field on the inner query is the db function call result, which of course doesn't match a field in the entities in the inner query: it has to perform a compiled version of the lambda on the entity and use the result of that in the comparison. The problem is: the lambda can't always produce the result as it's ran in-memory.
As outer query, the engine builds: select [key], [constant] from [group by query]
as inner query, it builds: select ... from [source of group by] where [keyfield1] in (values...)
It is possible to work around the issue and build the query though the problem arises where the two sets have to be merged. This is done by using the group of field pairs to field all elements in the inner query for a given row in the outer query. These are then placed in the slot of the constant and the whole set of rows of the outer query is then converted into a list of IGrouping<keytype, entity> objects.
The problem is to find a way to tie a row in the inner query to a row in the outer query. With a grouping on a field, that's easy, the field exists. With a grouping using a function call, it's not possible without running the function call in-memory as well and with that hope that the lambda which caused the function call to appear, produces the same result, which isn't guaranteed.
I don't see a reliable way to solve this particular case at this point. The query: var a1 = (from t in db.CustActivity where t.UserId == userId group t by t.ActivityDate.Date into g select new BusinessEntities.Activity.List { Date = g.Key }).ToList();
should work though...
I was hoping it would be possible though at the moment I don't see a way to do it, besides going the route of the slow inefficient way of how linq to sql does it.
If you really need this, you could go the low-level route and add a computed column to the CustActivity table which returns the date fragment of the ActivityDate field, you can then group on that field and return 'g', which works as the field is present in the entity.
(to grab the date fragment, do: DATEADD(ms, -DATEPART(ms, [LPLA_1].[OrderDate]), DATEADD(s, -DATEPART(s, [LPLA_1].[OrderDate]), DATEADD(n, -DATEPART(n, [LPLA_1].[OrderDate]), DATEADD(hh, -DATEPART(hh, [LPLA_1].[OrderDate]), [LPLA_1].[OrderDate])))) )