2017-02-20 16 views
1

私のforeachステートメントをループするときに、アプリケーションがタイムアウトエラーを返す問題があります。ご注意ください私は変更したり、私が照会しているテーブルのビューを作成することはできません。非効率的なLINQ Foreachステートメントタイムアウト

IEnumerable<MyTable> TContextData; 
if (!string.IsNullOrEmpty(id) 
    || !string.IsNullOrEmpty(name) 
    || !string.IsNullOrEmpty(cell) 
    ) 
{ 
    TContextData = (from e in db.mytable 
        where (!String.IsNullOrEmpty(e.id)) 
        select e); 
} 
else 
{ 
    TContextData = null; 
} 

List<EachC> mDatalist = new List<EachC>(); 

if (TContextData != null) 
{ 
    foreach (var i in TContextData.ToList()) 
    { 
     EachMR EachM = new EachMR(); 

     EachM.Feature = i.TRuid; 
     EachM.Feature2 = i.TRuid2; 
     EachM.Feature3 = i.TRuid3; 
     EachM.Date = GetInnerTextfromXML(EachM.Feature3, "/Sections/Multiple/Functions/Group/Date"); 
     mdatalist.Add(EachM); 
    } 
} 

反復する行は約40Kです。これをより効率的にする方法はありますか?

エラーメッセージ:型「System.OutOfMemoryExceptionに」の例外がSystem.Data.Entity.dllで発生したが、ユーザーコードで処理されなかった

は私が

にコンテキストにタイムアウトを増加していました
((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 0; 

しかし、それはまさにマスキングの問題ではありません。

+3

'mytable'行の内容全体が必要ですか?すべての単一の行は本当に "do stuff"の影響を受ける必要がありますか? 'e.id'をnullにすることができますか、空にするか、本当に両方のチェックを行う必要がありますか? iteratingを開始する前に2番目のクエリを '.ToList()'すると、それは違っていますか?変更をデータベースに保存する必要がありますか?あなたは 'do stuff 'の' mytable'の子テーブルにアクセスしていますか?( 'for'ループで遅れて実行されるクエリを見てください)?これをプロファイリングして、SQLが実行されていることを確認しましたか? 1の代わりに40,000件のクエリを実行している可能性があります。 –

+0

なぜ '.Take(1)'が 'foreach'のタイムアウトを防ぐのでしょうか? - つまり、明らかに1行しか返されませんが、空の(またはヌル)チェックを行う代わりに、なぜ1行しか取得できないのでしょうか? – gobes

+0

あなたのアプリケーションはどのようにホストされていますか?タイムアウトにはどれくらい時間がかかりますか?また、表示されているlinqではなく、 '#Do Stuff'の部分で問題が表示されないことがあります。あなたのコード、特に#Do Stuffの部分をプロファイリングして、どの部分が長すぎるかを確認する必要があります –

答えて

-1

正確なメッセージがなければ、タイムアウトがどこから来ているのかは分かりません。しかし、私はそれがSQLタイムアウトではないと思います。

実際にコードが実行しているのは、foreachで取得しようとしている各行のデータベースに対してクエリを実行することです。つまり、おそらく40,000クエリを実行している可能性があります。代わりに、データをメモリにロードして、.ToList()メソッドを使用してリスト上でコードを実行すると、クエリが1回実行されます。

IEnumerable TContextData; 

if (!string.IsNullOrEmpty(id) 
|| !string.IsNullOrEmpty(name) 
|| !string.IsNullOrEmpty(cell)) 
{ 
    TContextData = (from e in db.mytable where (!string.IsNullOrEmpty(e.id)) select e); 
} 

foreach(var i in TContextData.ToList()) 
{  
    //do stuff 
} 

また、私はすべてのコンテキストを持たずに話しています。あなたは.ToList()を助けることができるの削除EFLinqToSQL、またはIEnumerableに変換DataReader ...

+0

これは真実ではありません。ループ内の他の場所で 'TContextData'を使用しない限り、この呼び出しは単一のIEnumeratorを作成し、40000回実行されません。 – decPL

+0

おかげでゴブズ。私はこれを試してみましたが、これは私が受け取っているエラーです:{'例外' System.OutOfMemoryException '型の例外がスローされました。} – AMorrisey

+0

@decPL 'IEnumerator'は一度だけ作成され、コードがそれを列挙するときに 'Enumerator'の列挙と' List 'の列挙の違いは何ですか?そうでなければ遅延実行ですか?私はいつもEFがすべてのシングルラインのデータベースを照会しましたが(いくつかのクエリツリーマジックを使用しています)私はこの動作についていくつかの問題を抱えており、 'ToList'を使用すると、クエリの数が大幅に減りました。プロパティーのナビゲーションが原因でしょうか? – gobes

0

を使用している場合、答えは少し違うだろう。あなたのコードは、クエリーがリスト内で返すものすべてを不必要にバッファし、そのリストを反復処理します。 TContextDataをループするだけです。

関連する問題