0

WHERE-clause を動的に作成する特定のクエリの行をカウントしたいと考えています。

私が興奮したのは、これを 2 つの異なる方法で構築したときに見た違いでした。

1を試す

int resultsCount = context.MyView.Where(x => x.Id > 100000).Count();

私が見るプロファイラーでは、次のクエリが実行されていることがわかります。

SELECT 
[GroupBy1].[A1] AS [C1]
FROM ( SELECT 
    COUNT(1) AS [A1]
    FROM (SELECT 
      [MyView].[Id] AS [Id], 
      [MyView].[EventTypeId] AS [EventTypeId], 
      [MyView].[EventSourceId] AS [EventSourceId], 
      [MyView].[TraceLevelId] AS [TraceLevelId], 
      [MyView].[TimeCreated] AS [TimeCreated], 
      [MyView].[Data1MaxStr] AS [Data1MaxStr]
      FROM [dbo].[MyView] AS [MyView]) AS [Extent1]
    WHERE [Extent1].[Id] > 100000
)  AS [GroupBy1]

トライ2

しかし、複数の条件を確認する必要があり、すべての実行ですべての条件が満たされる必要はありません。そこでWHERE、動的に -clause を作成してみましたCOUNT(この投稿を参照):

var parameter = Expression.Parameter(typeof(MyView), "x");
Expression<Func<MyView, bool>> check1 = x => x.Id > 100000;
Expression expression = Expression.Constant(true);
expression = Expression.AndAlso(expression, Expression.Invoke(check1, parameter));
var lambda = Expression.Lambda<Func<MyView, bool>>(expression, parameter);

int resultsCount = context.MyView.Where(lambda.Compile()).Count();

同じ、または少なくとも同様のクエリが実行されることを期待しますが、代わりにプロファイラーに次のように表示されます。

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[EventTypeId] AS [EventTypeId], 
[Extent1].[EventSourceId] AS [EventSourceId], 
[Extent1].[TraceLevelId] AS [TraceLevelId], 
[Extent1].[TimeCreated] AS [TimeCreated], 
[Extent1].[Data1MaxStr] AS [Data1MaxStr]
FROM (SELECT 
      [MyView].[Id] AS [Id], 
      [MyView].[EventTypeId] AS [EventTypeId], 
      [MyView].[EventSourceId] AS [EventSourceId], 
      [MyView].[TraceLevelId] AS [TraceLevelId], 
      [MyView].[TimeCreated] AS [TimeCreated], 
      [MyView].[Data1MaxStr] AS [Data1MaxStr]
      FROM [dbo].[MyView] AS [MyView]) AS [Extent1]

ただしの値はresultsCount同じですが、なぜこれらのクエリがそれほど異なるのですか? また、LinQCOUNTは 2 番目のクエリの をどこで取得しますCOUNTか?

最初のクエリと同様のクエリを強制する方法を誰かに教えてWHEREもらえますか?

どんなヒントでも大歓迎です。

4

1 に答える 1

1

あなたはCompileあなたの表現を求めています。

これにより、 から に変換さExpression<Func<MyView, bool>>Func<MyView, bool>ます。ではなく単なるデリゲートであるため、 のオーバーロードのExpressionシグネチャとは一致しなくなり、オーバーロードのみと一致します。IQueryableWhereIEnumerable

これは、クエリが SQL に変換されていないことを意味します。フィルター処理をまったく行わずにデータのクエリを実行してから、クライアント側のオブジェクトに対して LINQ でフィルター処理を行っています。

クエリ プロバイダーによってクエリを SQL に変換する場合は、ラムダをコンパイルしないことが重要です。

于 2013-09-30T14:38:00.937 に答える