12

私が次のものを持っていると想像してください:

private IEnumerable MyFunc(parameter a)
{
   using(MyDataContext dc = new MyDataContext)
   {
      return dc.tablename.Select(row => row.parameter == a);
   }
}

private void UsingFunc()
{
   var result = MyFunc(new a());

   foreach(var row in result)
   {
      //Do something
   }
}

ドキュメントによると、linqの実行は、foreachの行で発生する結果を実際に列挙するまで延期されます。ただし、usingステートメントは、MyFunct()の呼び出しの最後にオブジェクトを確実に収集するように強制する必要があります。

ディスポーザが実行されたり、結果が実行されたりするのはいつですか?

私が考えることができるのは、遅延実行がコンパイル時に計算されることだけです。したがって、実際の呼び出しはコンパイラによってforeachの最初の行に移動され、usingが正しく実行されますが、foreach行まで実行されませんか?助けることができる教祖はそこにいますか?

編集:注:このコードは機能しますが、方法がわかりません。

少し読んだところ、コードでToList()拡張メソッドを呼び出したことに気づきました。これはもちろん結果を列挙します。チェックされた回答の動作は、実際に回答された質問に対して完全に正しいものです。

ご迷惑をおかけして申し訳ありません。

4

2 に答える 2

13

私はそれが単に機能しないことを期待します。はSelect延期されるため、この時点ではデータは消費されていません。ただし、(を離れる前にMyFunc)データコンテキストを破棄したため、データを取得することはできません。より良いオプションは、データコンテキストをメソッドに渡して、コンシューマーが有効期間を選択できるようにすることです。また、コンシューマーが結果を「作成」できるように(IQueryable<T>つまり、// /などを追加し、最終的なクエリに影響を与えるように)戻ることをOrderByお勧めします。SkipTakeWhere

// this could also be an instance method on the data-context
internal static IQueryable<SomeType> MyFunc(
    this MyDataContext dc, parameter a)
{
   return dc.tablename.Where(row => row.parameter == a);
}

private void UsingFunc()
{
    using(MyDataContext dc = new MyDataContext()) {
       var result = dc.MyFunc(new a());

       foreach(var row in result)
       {
           //Do something
       }
    }
}

更新:(コメント)実行を延期したくない場合(つまり、呼び出し元がデータコンテキストを処理したくない場合)、結果を評価する必要があります。.ToList()これを行うには、または結果を呼び出し.ToArray()て値をバッファリングします。

private IEnumerable<SomeType> MyFunc(parameter a)
{
   using(MyDataContext dc = new MyDataContext)
   {
      // or ToList() etc
      return dc.tablename.Where(row => row.parameter == a).ToArray();
   }
}

この場合、延期したままにする場合は、「イテレータブロック」を使用する必要があります。

private IEnumerable<SomeType> MyFunc(parameter a)
{
   using(MyDataContext dc = new MyDataContext)
   {
      foreach(SomeType row in dc
          .tablename.Where(row => row.parameter == a))
      {
        yield return row;
      }
   }
}

これは、データコンテキストを渡さずに延期されるようになりました。

于 2009-01-19T06:22:04.043 に答える
8

このサンプルコードを含む、この問題に対する別の遅延実行ソリューションをここに投稿しました。

IQueryable<MyType> MyFunc(string myValue)
{
    return from dc in new MyDataContext().Use()
           from row in dc.MyTable
           where row.MyField == myValue
           select row;
}

void UsingFunc()
{
    var result = MyFunc("MyValue").OrderBy(row => row.SortOrder);
    foreach(var row in result)
    {
        //Do something
    }
}

Use()拡張メソッドは、基本的に遅延usingブロックのように機能します。

于 2009-07-23T08:38:20.557 に答える