Как выполнить LINQ to SQL скомпилированный запрос, который содержит условный оператор?

Мне нужно скомпилировать запрос LINQ-to-SQL, который содержит условный оператор "?:". Я могу скомпилировать такой запрос, но проблема в том, что он не работает, когда я пытаюсь его выполнить.

Вот простое воспроизведение:

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);

Вывод консоли показывает, что ожидаемый SQL-оператор был выполнен:

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

Но похоже, что при попытке перечислить набор результатов из базы данных происходит сбой.

Исключением является InvalidOperationException с сообщением "Последовательность содержит более одного элемента".

Трассировка стека:

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() ...

Кто-нибудь может предоставить способ заставить это выполнить? По причинам, в которые я не могу войти, я не могу переместить эту условную логику за пределы выражения - она ​​должна быть частью скомпилированного запроса.

1 ответ

Решение

Это, вероятно, ошибка. Ошибка в том, что они не выдают ошибку, что вы не можете переключаться между несколькими запросами во время выполнения. Они, вероятно, никогда не намеревались использовать это CompiledQuery.Compile,

Скомпилируйте два запроса или: UserId >= (option ? 0 : 5) && UserId < (option ? 5 : int.MaxValue), Этот предикат все еще SARGable.

Другие вопросы по тегам