2

条件付きの "?:" 演算子を含む 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() ...

誰でもこれを実行する方法を提供できますか? 説明できない理由により、この条件付きロジックを式の外に移動することはできません。これは、コンパイルされたクエリの一部である必要があります。

4

1 に答える 1

1

おそらくバグです。バグは、複数のクエリ間でランタイムを切り替えることができないというエラーが表示されないことです。彼らはおそらく、このようなCompiledQuery.Compile.

2 つのクエリをコンパイルしますUserId >= (option ? 0 : 5) && UserId < (option ? 5 : int.MaxValue)。この述語はまだ SARGable です。

于 2014-02-27T10:22:53.330 に答える