2

次のコードでは、「dl.DamageCount> 5」をクエリに直接入れた場合と、「dl.DamageCount> 5」をメソッドまたは関数に移動してクエリから呼び出す場合との違いはありますか?

メソッドに移動すると、クエリが正しく機能しないようです。実際、関数/メソッドは、条件の評価に関係なく常にtrueを返すようです。Linq-to-NHibernateを使用しています。

 var q = from dl in session.Linq<DamageList>()
            where
            dl.DamageCount > 5
4

1 に答える 1

4

できる最善のことは、述語をでキャプチャすることですExpression<>。メソッドはすでにILにコンパイルされているため、Linqプロバイダーがメソッドを選択することはできません。

Expression<Func<DamageList, bool>> predicate = item => item.DamageCount > 5;

次に、その述語を直接Where:に渡すことができます。

var q = session.Linq<DamageList>().Where(predicate);

このような2つの式を動的に組み合わせる場合は、両方のコードを1つの式に記述するか、両方を別々の式にキャプチャします。渡されるものを参照するためにそれぞれが必要になるため、これは複雑になりますitem。これは実際には別の質問であり、すでに質問されています。Expression<Func <MyClass、bool >>述語を動的に作成するにはどうすればよいですか?

&& oeratorを使用して複合述語を記述し、それを式に取り込むことができます。

Expression<Func<DamageList, bool>> predicate = 
    dl => dl.DamageCount > 5 && dl.Name.Contains(criteria);

あなたはそのような式でメソッドを呼び出すことについて尋ねます-まあ、その例はメソッドを呼び出します!

Expressionさまざまなタイプのノードのツリーを構築します。どこかに含まれるのは、のメソッドを呼び出すように指示するメソッド呼び出しノードContainsですstring(がであると仮定しNameますstring)。したがって、これは式に埋め込まれたメソッド呼び出し命令の例です。これが機能するためには、Linqプロバイダーはそのメソッドが何をするかを知っている必要があるので、それを同等のSQLに変換できます(通常のORMシステムの場合のように)。

したがって、特定の標準メソッド呼び出しを式に埋め込むことができます。Linqプロバイダーがそれらについて知っている必要があります。の方法はstring明確に定義されていますが、すべてのプロバイダーが必ずしもすべてを処理できるわけではありません。

Linqプロバイダーが、追加のメソッドを処理する独自の拡張機能を追加できるようにすることは不可能ではありませんが、それをサポートするものはありません(明らかに、システムがオープンソースの場合は、独自の拡張機能を追加できます)。

要約すると、Linqプロバイダーには、リモートデータベース内などの別のコンテキストで実行するために、SQLなどの他の言語に変換するために分析できる式ノードのツリーが必要です。通常のメソッドを作成する場合、C#コンパイラはそれらを式ノードではなく低レベルの実行可能ILにコンパイルします。つまり、これは行き止まりのようなものです。ILを式ノードに戻すための組み込み機能はありません。

于 2010-02-21T11:31:58.113 に答える