2009-08-30 9 views
4

私は、次のLINQクエリを持っている:エンティティへのLINQ:分割メソッドを条件として使用できないのはなぜですか?

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

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

毎回私は、私は次のエラーを取得するこのクエリを実行します。

「LINQメソッドを認識しないエンティティに「ブールが含まれて[文字列](System.Collections.Generic.IEnumerable`1 [可能System.String] 、System.String) 'メソッドであり、このメソッドはストア式に変換できません。

私は何をしようとしているのですか?

+4

実際にブール演算の結果をtrと比較する理由はありませんue。返されたブールを使用してください。 –

+0

明らかに...私はLINQを使用していたので、この方法でやっていました。 – James

答えて

1

あなたはそうはい、性能の損失があるだろう、クライアント上の非インデックス付きのワイルドカード文字列マッチングを行うこととしています。

1つのテーブルフィールドに複数のキーワードがあるのはなぜですか?アクティビティごとにいくつかのキーワードレコードがあるActivityKeywordsテーブルを持つように、正規化することができます。

活動(ACTIVITY_ID、.../*キーワードフィールドを削除* /)---> ActivityKeywords(ACTIVITY_ID、keyword_id)--->キーワード(keyword_id、値)

非第1正規形をチェック:http://en.wikipedia.org/wiki/Database_normalization

EDIT:たとえあなたが1つの列に固執していたとしても、厳密な構文( 'keyword1、keyword2、...、キーワードN')があればすべてを処理する方法があります。

var aKeyword = "ACT"; 
var results = (from a in db.Activities 
       where a.Keywords.Contains("," + aKeyword) || a.Keywords.Contains(aKeyword + ",") 
       select a; 
+0

本当に使いやすさのためだけでした。ほとんどのアクティビティにはいくつかのキーワードしかないので、別のテーブルを必要としていませんでした。しかし、私は実際にあなたが示唆したことをやっているとは思っていませんでした...それはおそらくよりよい変化になるでしょう!ありがとう。 – James

+0

私はキーワードのための厳密な構文を持っています、それはあなたが示唆したように、すなわちキーワード、キーワード、キーワードです。しかし、私は別のテーブルに行くことにしました。ありがとう。 – James

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は、初期フィルタのビットをさせ、その後道の残りの部分を下にフィルタリングすることがありますLINQツーエンティティせます

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)); 

それは(string.Containsを理解し、フィルタを行います同様のクエリになります)、いくつかのデータをフィルタリングし、オブジェクトが戻ったら、LINQ-to-Objectsを介して必要な実際のフィルタを適用します。 ToList()呼び出しは、LINQ-to-Entitiesにクエリを実行させてオブジェクトを構築させ、LINQ-to-Objectsをクエリの2番目の部分を実行するエンジンとして許可します。

+1

@James - はい、前者はかなりのパフォーマンスを必要とします。後者はそれほどではありません(テーブル/インデックススキャンが必要ですが、候補行のみを返します)。これが大量に実行されるものであれば、DB事前分割(つまりアクティビティごとにキーワードごとに1つの行があるテーブル - Yannickの提案)にキーワードを格納することをお勧めします。次に、DBがうまく処理できるクエリとして記述することができます。 –

+0

ええ、私はYannickの提案を使うことに決めました! – James

+0

このアプローチを使用するときは、2つの一致を行うだけで、すべての処理がサーバー側で行われるようにすることをお勧めします。 a.Keywords.Contains( "、" + aKeyword)|| a.Keywords.Contains(aKeyword + "、") –

0

私の推測では、スプリットと呼んでいます。それは配列を取る必要があります。たぶん、LINQの内の別の分割は、それが発見し、あなたに珍しいエラーを与えているがあります:

これは、オブジェクトへのLINQのために働く:

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 

、を考えますそれは全く分裂が必要ですか? foobarにヒットしたくない場合を除き、a.Contains("foo")で十分でしょう。

+0

ええdefo分割が必要です(言及したように)キーワードは他のキーワードの一部にすることができます。完全一致が必要です。 – James

0

クライアント側をフィルタリングする前にスーパーセットで推測するよりも効率的でなければならない解決方法は、look at this question about L2E and .Containsです。大きなデータセットのパフォーマンスの考慮事項に対応して

関連する問題