2015-01-14 17 views
10

背景奇妙な行動EndsWithメソッド

は、私は1つの列のみを含むテーブルを持っている:名前を。 4行は、それだけ ありますが、私は

var email = "[email protected]"; 
Table.Where(x => email.EndsWith(x.Name)); 

を照会した場合、私は空のリストを取得します

問題

| Name  | 
| test1.com | 
| test2.com | 
| test3.com | 
| test4.com | 

を言います。私が最初にすべての行を照会し、この

var email = "[email protected]"; 
Table.ToList().Where(x => email.EndsWith(x.Name)); 

のようにメモリにどこに計算すると、私はリストが正しいだけtest2.comが含まれ得るでしょう。

最初のクエリのために生成されたSQLは、私が交換しようとした

SELECT "Extent1"."Name" AS "Name" 
FROM "USER"."Table" "Extent1" 
WHERE ((NVL(INSTR(REVERSE(:p__linq__0), REVERSE("Extent1"."Name")), 0)) = 1) 

です:p__linq__0「[email protected]」とのsqldeveloperでクエリを実行すると、結果は正しいです。

詳細情報

私はEndsWith()を変更した場合は(入って)、問題が消えてしまいます。ここで

SELECT "Extent1"."Name" AS "Name" 
FROM "USER"."Table" "Extent1" 
WHERE ((NVL(INSTR(:p__linq__0, "Extent1"."Name"), 0)) > 0) 

は)(のために生成されたSQLが含まれていますが、EndsWithまたはREVERSE方法と間違って何任意のアイデアを持っているのですか?

環境

  • EF5.0
  • .NET4.5
  • Oracle11g
  • この行は私に関係している3
+3

データベースが(大文字と小文字を区別しない)CIに設定されていること(両方のシナリオのために)覚えているこれは、我々は常にSQLに直接IQueryablesを使用している場合、SQL EntityFrameworkが生成するチェックすべき理由として良い例です。なぜそれがSQLを生成するのか説明できません...しかし、私が生成するすべてのIQueryableで確認するのが一般的な方法になっています。 – Derek

答えて

3

をリリースODP.NET11.2 EFを使用する人々と共通の落とし穴:

これは、実際にメモリに テーブル全体をマテリアライズした後、C#で EndsWithを実行するため
Table.ToList().Where(x => email.EndsWith(x.Name)); 

Table.ToList()は最悪の部分です。 この行:

Table.Where(x => email.EndsWith(x.Name)); 

表は、合理的な大きさに成長したときに、それは恐ろしく遅くなりますように私はちょうど一般的な原理にこのアプローチを警告します。クエリは、クエリを構築するよう、電子メールのドメインを分割することにより、データベースを打つ前に、重い物を持ち上げる操作を行うことができます。

var email = "[email protected]"; 

/* You should null check this of course and not just assume a match was found */ 
var domain = Regex.Match(email , "@(.*)").Groups[1].Value; 

/* Note: ToList() materialisation happens at the end */ 
var result = Table.Where(x => x.Name == domain).ToList(); 

さらに、あなたは電子メールを格納する列のドメイン名に一致する必要がある場合私の優先的なアプローチは、電子メールを分割し、インデックスを作成してマッチする別の列にドメイン名を格納することです。これは規模が大きくなり、管理が簡単になります。最近のデータは安価であることを覚えています。特に、インデックスを作成できないテーブルスキャンと比較して、

はまた

+0

ですから、答えはEndsWithはEFではサポートされていませんか?私はこれについて書かれた文書は見当たらなかった。リンクがありますか? – Moozz

+0

いいえ、答えは私が上で言ったことです...あなたはそれを必要としません。 C#でドメイン名を抽出し、それをクエリに渡します。私の答えはc#とsqlの境界を十分に理解していないと思っているので、私の答えを再度読んでください。 EFテーブルエンティティでToList()を呼び出すと、パフォーマンスの面で恐ろしくスケールされないテーブル全体がマテリアライズされます(メモリに格納されます)。それは物事を明確にするか?他に混乱していることはありますか? –

+0

ToList()はすべての行をメモリにプルすることを理解しています。 EndsWithがうまくいかない理由だけが不思議です。生成されたSQLはOKのようですが、うまくいきません。とにかく、あなたは私がEndsWithを使う必要はないということは間違いありません。 – Moozz