CompiledQuery problem with parameter

Discussion of open issues, suggestions and bugs regarding LinqConnect – Devart's LINQ to SQL compatible ORM
Post Reply
crazypit
Posts: 163
Joined: Wed 15 Apr 2009 08:43

CompiledQuery problem with parameter

Post by crazypit » Mon 15 Mar 2010 11:08

Hello,

I try to pass to a CompiledQuery.Compile method a parameter of type IQueryable in order to use it with the inner query and join with it. The parameter is the result of an other CompiledQuery.Compile method:

public partial class Udf
{
public static Func> ClientsService_GetUdfsByRefType =
CompiledQuery.Compile(
(ExrayDataContext dataContext, long RefTypeId, string refType) =>
(from objUdf in dataContext.Udfs
from objGroupAssoc in dataContext.UdfsGroups
from objGroup in dataContext.Udfgroups
where objGroup.SubType_Str == UdfGroupSubTypeEnum.CustManagMain.ToString("d") &&
objGroup.Type_Str == UdfGroupTypeEnum.ClientView.ToString("d") &&
objGroup.UdfType_Str == UdfGroupUdfTypeEnum.Customer.ToString("d") &&
objGroupAssoc.UdfgroupId == objGroup.Id &&
objUdf.Id == objGroupAssoc.UdfId &&
(objUdf.RefTypeId == RefTypeId || objUdf.RefTypeId == null) &&
objUdf.RefType_Str == refType &&
objUdf.Status_Str == ActivationStatusEnum.Active.ToString("d") &&
objUdf.AccessType_Str != UDFAccessTypeEnum.Internal.ToString("d")
select objUdf));


public static Func, IQueryable>
ClientsService_GetUdfsByRefType_2 =
CompiledQuery.Compile(
(ExrayDataContext dataContext, IQueryable queryUdfs) =>
from objDefaultValue in dataContext.UdfsDefaultValues
from objUdf in queryUdfs
where objUdf.Id == objDefaultValue.UdfId
select objDefaultValue);
}


If i try to run this:

var defaultValuesList =
Udf.ClientsService_GetUdfsByRefType_2(dataContext,
Udf.ClientsService_GetUdfsByRefType(dataContext, RefTypeId, refType.ToString("d"))).
ToList();

I get a "Parameters cannot be sequences." exception with the following stack trace:

at Devart.Data.Linq.Provider.Query.bk.a(SqlNode A_0)
at Devart.Data.Linq.Provider.Query.bk.a(Expression A_0)
at Devart.Data.Linq.Provider.Query.bk.a(Expression A_0, Expression A_1, Expression A_2)
at Devart.Data.Linq.Provider.Query.bk.b(MethodCallExpression A_0)
at Devart.Data.Linq.Provider.Query.bk.j(Expression A_0)
at Devart.Data.Linq.Provider.Query.bk.a(Expression A_0)
at Devart.Data.Linq.Provider.Query.bk.a(Expression A_0, LambdaExpression A_1)
at Devart.Data.Linq.Provider.Query.bk.b(MethodCallExpression A_0)
at Devart.Data.Linq.Provider.Query.bk.j(Expression A_0)
at Devart.Data.Linq.Provider.Query.bk.a(Expression A_0)
at Devart.Data.Linq.Provider.Query.bk.d(Expression A_0, Expression A_1)
at Devart.Data.Linq.Provider.Query.bk.b(MethodCallExpression A_0)
at Devart.Data.Linq.Provider.Query.bk.j(Expression A_0)
at Devart.Data.Linq.Provider.Query.bk.a(LambdaExpression A_0)
at Devart.Data.Linq.Provider.Query.bk.j(Expression A_0)
at Devart.Data.Linq.Provider.Query.bk.i(Expression A_0)
at Devart.Data.Linq.Provider.DataProvider.a(Expression A_0)
at Devart.Data.Linq.Provider.DataProvider.i(Expression A_0)
at Devart.Data.Linq.CompiledQuery.a(e A_0)
at Devart.Data.Linq.CompiledQuery.a(DataContext A_0, Object[] A_1)
at Devart.Data.Linq.CompiledQuery.Invoke[a,b,c](a A_0, b A_1)

crazypit
Posts: 163
Joined: Wed 15 Apr 2009 08:43

Post by crazypit » Mon 15 Mar 2010 11:13

This is a very serious limitation. Imagine all the cases where a "Where" clause is incrementally built according to parameters. If we cannot compile each query and then pass it as a parameter to the next, a large amount of complex queries are left outside the performance gain of pre-compilation.

AndreyR
Devart Team
Posts: 2919
Joined: Mon 07 Jul 2008 13:16

Post by AndreyR » Tue 16 Mar 2010 13:51

Unfortunately, we are unable to provide support for this scenario. The reason is the fact that any query can be
passed as a parameter instead of IQueryable (possibly not the one you have written).
So there is no possibility to compile a query with unknown text.

crazypit
Posts: 163
Joined: Wed 15 Apr 2009 08:43

Post by crazypit » Tue 16 Mar 2010 15:09

I'm not talking about the classic kind of parameter and my example do not give the correct meaning of what i'm trying to do...

Obviously, the compiled query means that the SQL is generated and therefore we cannot pass an IQueryable as a parameter, because it will change the final SQL.

What i'm talking about is a way to provide the IQueryable to be compiled not in compile time, but in runtime.

The input of a CompiledQuery is essentially an IQueryable object. There can be parameters as long as they don't change the shape of the final expression. That is all. So, why does the developer has to provide the IQueryable at design time only and not be able to provide it at runtime using some logic? The first time the IQueryable is provided, it should be compiled and this is the one to be used whenever the delegate is called.

AndreyR
Devart Team
Posts: 2919
Joined: Mon 07 Jul 2008 13:16

Post by AndreyR » Wed 17 Mar 2010 15:56

The problem is in IQueryable in the parameter list of CompiledQuery.Compile(). It can be modified and that's the reason of the problem.
We will investigate the possibility to implement the workaround to implement the scenario you describe, because it is reasonable. I will let you know about the results.

AndreyR
Devart Team
Posts: 2919
Joined: Mon 07 Jul 2008 13:16

Post by AndreyR » Mon 29 Mar 2010 07:10

Unfortunately, we don't have technical possibility to implement any workaround solution at the moment.

Post Reply