6

次の LINQ クエリがあります。

var aKeyword = "ACT";
var results = from a in db.Activities
              where a.Keywords.Split(',').Contains(aKeyword) == true
              select a;

キーワードはカンマ区切りのフィールドです。

このクエリを実行するたびに、次のエラーが発生します。

「LINQ to Entities はメソッド 'Boolean Contains[String](System.Collections.Generic.IEnumerable`1[System.String], System.String)' メソッドを認識せず、このメソッドはストア式に変換できません。」

私がやろうとしていることの代替手段は何ですか?

4

4 に答える 4

8

問題は、LINQ-to-Entites が指定したすべてを SQL に変換してデータベースに送信する必要があることです。

それが本当に必要な場合は、LINQ-to-Entities にすべてのデータを強制的に引き戻し、LINQ-to-Objects に条件を評価させる必要があります。

元:

var aKeyword = "ACT";
var results = from a in db.Activities.ToList()
              where a.Keywords.Split(',').Contains(aKeyword) == true
              select a;

ただし、これにより、アクティビティ テーブルからすべてのオブジェクトが引き戻されることに注意してください。別の方法として、DB に最初のフィルターを少し実行させ、その後、残りの部分をフィルター処理することもできます。

var aKeyword = "ACT";
var results = (from a in db.Activities
              where a.Keywords.Contains(aKeyword)
              select a).ToList().Where(a => a.KeyWords.Split(',').Contains(aKeyword));

これにより、LINQ-to-Entities が理解できるフィルターを実行し (string.Contains が like クエリになります)、データの一部をフィルター処理し、オブジェクトが戻ってきたら、LINQ-to-Objects を介して必要な実際のフィルターを適用します。 . ToList() 呼び出しは、LINQ-to-Entities にクエリを実行させてオブジェクトを構築させ、LINQ-to-Objects がクエリの 2 番目の部分を実行するエンジンになるようにします。

于 2009-08-30T19:45:20.613 に答える
6

大きなデータセットでのパフォーマンスに関する考慮事項に応じて:

クライアントでインデックス化されていないワイルドカード文字列の照合を行うため、はい、パフォーマンスが低下します。

1 つのテーブル フィールドに複数のキーワードがある理由はありますか? これを正規化して、アクティビティごとに多数のキーワード レコードを持つ ActivityKeywords テーブルを作成できます。

Activities(activity_id, ... /* キーワード フィールドを削除 */) ---> ActivityKeywords(activity_id, keyword_id) ---> Keywords(keyword_id, value)

非第 1 正規形を確認してください: http://en.wikipedia.org/wiki/Database_normalization

EDIT:また、1つの列に固執する場合でも、サーバー側ですべてを行う方法があります(厳密な構文がある場合:「keyword1、keyword2、...、keywordN」):

var aKeyword = "ACT";
var results = (from a in db.Activities
              where a.Keywords.Contains("," + aKeyword) || a.Keywords.Contains(aKeyword + ",")
              select a;
于 2009-08-30T20:35:30.137 に答える
0

私の推測では、Split を呼び出す方法です。配列を取る必要があります。おそらく、Linq に別の Split があり、異常なエラーが検出されて発生する可能性があります。

これは、Linq to Objects で機能します。

 var dataStore = new List<string>
                    {
                        "foo,bar,zoo",
                        "yelp,foo",
                        "fred",
                        ""
                    };
 var results = from a in dataStore
               where a.Split(new[] {','}).Contains("foo")
               select a;

 foreach (var result in results)
 {
     Console.WriteLine("Match: {0}", result);
 }

以下を出力します。

Match: foo,bar,zoo
Match: yelp,foo

実際、考えてみると、そもそも分割が必要ですか? a.Contains("foo")あなたには十分かもしれません(あなたがヒットしたくない場合を除きますfoobar)。

于 2009-08-30T19:48:22.447 に答える
0

クライアント側をフィルタリングする前にスーパーセットを推測するよりも効率的なソリューションについては、L2E と .Contains に関するこの質問を参照してください。

于 2009-08-30T20:12:49.637 に答える