Question

I need to compile a LINQ-to-SQL query that contains a conditional "?:" operator. I'm able to compile such a query, but the problem is that it fails when I try to execute it.

Here is a simple repro:

MyContext myContext = new MyContext(sqlConnection);
myContext.Log = Console.Out;

var cq = CompiledQuery.Compile(
         (MyContext context, bool option) =>
                option ? context.GetTable<User>().Where(x => x.UserId > 5)
                       : context.GetTable<User>().Where(x => x.UserId < 5));

//Crashes when trying to invoke.
cq.Invoke(myContext, true);

The console output shows the expected sql statement was executed:

SELECT [t0].[UserId],...
FROM [dbo].[User] AS [t0]
WHERE [t0].[UserId] > @p0
-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [5]

But it appears that the execution fails while trying to enumerate the result set from the database.

The exception is an InvalidOperationException, with message "Sequence contains more than one element."

Stack trace is:

at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)
at Read_User(ObjectMaterializer`1 )
at System.Data.Linq.SqlClient.ObjectReaderCompiler.ObjectReader`2.MoveNext()
at Program.Main() ...

Can anyone provide a way to get this to execute? For reasons that I cannot go into, I cannot move this conditional logic outside of the expression - it must be a part of the compiled query.

Était-ce utile?

La solution

It probably is a bug. The bug being that they do not give you an error that you cannot runtime-switch between multiple queries. They probably never intended this usage of CompiledQuery.Compile.

Compile two queries, or: UserId >= (option ? 0 : 5) && UserId < (option ? 5 : int.MaxValue). This predicate is still SARGable.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top