- Home
- LLBLGen Pro
- Bugs & Issues
ORMQueryConstructionException when trying to use generics
Joined: 12-May-2005
Using LLBLGen 4.2, VS2015, SQL2012
Hello, I have simplified this case to a very simple data model : 2 tables "Company" and "Group", with a n-1 relationship, so a company has a FK to a group. At one time I need to fetch the Companies for a given group, so that's very simple:
using (var adapter = CreateAdapter())
{
var metaData = new LinqMetaData(adapter);
var query = metaData.Company.Where(x => x.GroupId == groupid);//groupid is a nullable Int64 passed in via parameter
var result = await query.ToListAsync();
return result;
}
Now, in the future I foresee to have a lot of different entities to have a Group, so I've made an interface :
public interface IHasGroup
{
long GroupId { get; }
}
and in the custom class of the CompanyEntity just add this interface.
public partial class CompanyEntity : IHasGroup {} //the GroupId is a generated field from LLBLGen
Then I've made a fluent generic extension method :
public static class QueryFilterExtensions
{
public static IQueryable<T> ApplyGroupFilter<T>(this IQueryable<T> query, int? groupId) where T : IHasGroup
{
if (groupId.HasValue)
query = query.Where(x => x.GroupId == groupId.Value);
return query;
}
}
so I could use the code :
using (var adapter = CreateAdapter())
{
var metaData = new LinqMetaData(adapter);
var query = metaData.Company.ApplyGroupFilter(groupid);
//var query = metaData.Company.Where(x => x.GroupId == groupid);
var result = await query.ToListAsync();
return result;
}
But this results in the error :
Message: "An error has occurred.", ExceptionMessage: "The binary expression '(Convert(Entity(CompanyEntity)).GroupId == 1)' can't be converted to a predicate expression.", ExceptionType: "SD.LLBLGen.Pro.ORMSupportClasses.ORMQueryConstructionException", 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.LLBLGenProProviderBase.HandleExpressionTree(Expression expression) at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.<PerformExecuteAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable
1.ConfiguredTaskAwaiter.GetResult() at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.<ExecuteAsync>d__2
1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable1.ConfiguredTaskAwaiter.GetResult() at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProQuery
1.<ExecuteAsync>d__41.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable
1.ConfiguredTaskAwaiter.GetResult() at SD.LLBLGen.Pro.LinqSupportClasses.QueryableExtensionMethods.<ToListAsync>d__41.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter
1.GetResult() at Bestmix.Backend.Business.Repositories.EntityRepositories.CompanyRepository.<GetEntitiesForOverview>d__0.MoveNext() in D:\FAAS2.0\Src\Bestmix.Poc\Bestmix.Backend.Business\Repositories\EntityRepositories\CompanyRepository.cs:line 25 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at Bestmix.Backend.WebApi.Controllers.EntityController
1.<GetEntitiesForOverview>d__2.MoveNext() in D:\FAAS2.0\Src\Bestmix.Poc\Bestmix.Backend.WebApi\Controllers\EntityController.cs:line 37 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at System.Threading.Tasks.TaskHelpersExtensions.<CastToObject>d__3
1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter
1.GetResult() at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()" }
If I change the extension method to a non-templated generic :
public static IQueryable<CompanyEntity> ApplyGroupFilter(this IQueryable<CompanyEntity> query, int? groupId)
{
if (groupId.HasValue)
query = query.Where(x => x.GroupId == groupId.Value);
return query;
}
then it works, but of course I can only use it on CompanyEntity's , and I would like to use it on all entities that implement "IHasGroup"
Is there something I'm missing here ?
Kind regards, Sven.
Joined: 12-May-2005
Fixed !!!
It seems that all I needed to do was add "CommonEntityBase" as a generic requirement,
so
public static IQueryable<T> ApplyGroupFilter<T>(this IQueryable<T> query, int? groupId) where T : [b]CommonEntityBase[/b], IHasGroup
instead of
public static IQueryable<T> ApplyGroupFilter<T>(this IQueryable<T> query, int? groupId) where T : IHasGroup
So this thread can be closed, I hope someone else finds this useful when they encounter the same error when trying to dynamically construct queries ....
Kind regards, Sven.