web-dev-qa-db-ja.com

LINQ式を翻訳できなかったため、ローカルで評価されます

EntityFramework Coreでこの警告が表示されるのはなぜですか?

私はすでにMSSQL日付ベースを大文字と小文字を区別するように設定しています。

Latin1_General_100_CS_AS

var test = await _context.Students
                .FirstOrDefaultAsync(m => m.LastName.Equals("ALEXANDER", StringComparison.InvariantCultureIgnoreCase));

Microsoft.EntityFrameworkCore.Query:Warning:LINQ式 'where [m] .LastName.Equals( "ALEXANDER"、InvariantCultureIgnoreCase)'は翻訳できず、ローカルで評価されます。

3
Aorus1337

IEnumerableIqueryableの違いに注意する必要があります。

IEnumerableオブジェクトは、一連のオブジェクトを表します。これは、このシーケンスを列挙するためにすべてを保持します。シーケンスの最初の要素を要求できます。要素を取得したら、次の要素がある限り、次の要素を要求できます。

IQueryableオブジェクトはIEnumerableのように見えますが、列挙可能なシーケンスを表すのではなく、IEnumerableシーケンスを取得する可能性を表しています。

IQueryableオブジェクトはExpressionProviderを保持します。 Expressionは、照会する必要があるものを表す一般的な説明です。 Providerは、クエリを実行するユーザー(通常はデータベース管理システム)と、このDBMSとの通信に使用される言語(通常はSQL)を認識しています。

GetEnumeratorMoveNextを明示的に使用するか、foreach、ToList、Max、FirstOrDefaultなどを呼び出して暗黙的にIQueryableの列挙を開始すると、GetEnumeratorとMoveNextの呼び出しの内部で、式はプロバイダーに送信されます。プロバイダーはそれをSQLに変換し、DBMSからデータをフェッチします。フェッチされたデータはIEnumerableとして返され、GetEnumeratorおよびMoveNextが呼び出されます。

したがって、GetEnumeratorとMoveNextを呼び出す前にクエリは実行されません。

これは私の質問と何をしているのですか?

エンティティフレームワークは、クラスとメソッドを、認識しているSQLにのみ変換できます。 Entity Frameworkはあなた自身の機能を知りません。実際、エンティティフレームワークでサポートされていないLINQ関数がいくつかあります。 サポートされているおよびサポートされていないLINQメソッドを参照してください

サポートされていないメソッドの1つはString.Equals(string, StringComparison)です。この関数を使用すると、コンパイラーは文句を言わず、実行時にこのエラーが表示されます。これは、関数が呼び出される前に、最初にデータがフェッチされることを示しています。これは非効率的な動作につながる可能性があります。

あなたのLINQステートメントは(問題の一部ではなく、非同期待機を除外して)等しいです

var test = dbContext.Students
    .Where(student => student.LastName.Equals("ALEXANDER", StringComparison.InvariantCultureIgnoreCase))
    .FirstOrDefault();

Equalsは使用できないため、警告はWhereが実行される前にデータがローカルにフェッチされることを示しています。したがって、Whereを通過しないいくつかのアイテムがDBMSからローカルプロセスに転送される可能性があります。

データベースで大文字と小文字の区別を無視できる場合は、コードを次のように変更することを検討してください。

var test = dbContext.Students
    .Where(student => student.LastName == "ALEXANDER")
    .FirstOrDefault();

これにより、次のようなSQLステートメントが生成されます。

SELECT TOP 1 * from myDatabase.Students where LastName = "ALEXANDER"

(これが正しいSQLであるかどうかはわかりません。エンティティフレームワークを使用しているので、私のSQLは少し錆びています。Gistが表示されると思います)

5

EntityFrameworkはEquals("ALEXANDER", StringComparison.InvariantCultureIgnoreCase)をSQLに変換できないため、代わりにすべてのStudentテーブルをメモリにロードし、等式を満たす最初のエントリを検索します。

1
Elias N