8

更新- 答えは明らかに、DbLinq がDispose()適切に実装されていないことです。ああ!


以下はあらゆる種類の誤解を招くものです-結論:DbLinqは(まだ)LinqToSqlと同等ではありません.最初にこの質問をしたときに想定したように. 注意して使用してください!

DbLinq でリポジトリ パターンを使用しています。私のリポジトリ オブジェクトは を実装IDisposableし、Dispose()メソッドDispose()DataContext. リポジトリを使用するときはいつでも、次usingのようにブロックでラップします。

public IEnumerable<Person> SelectPersons()
{
    using (var repository = _repositorySource.GetPersonRepository())
    {
        return repository.GetAll(); // returns DataContext.Person as an IQueryable<Person>
    }
}

このメソッドは を返すので、私の理解が正しければ、次の例のように (たとえば、リストまたは配列に変換するか、ループで使用することによって) をトラバースするIEnumerable<Person>まで、データベースのクエリは実際には行われません。Enumerable<Person>foreach

var persons = gateway.SelectPersons();
// Dispose() is fired here
var personViewModels = (
    from b in persons
    select new PersonViewModel
    {
        Id = b.Id,
        Name = b.Name,
        Age = b.Age,
        OrdersCount = b.Order.Count()
    }).ToList(); // executes queries

この例でDispose()は、 は set の直後に呼び出されますpersons。これは であり、IEnumerable<Person>呼び出されるのはそのときだけです。

だから、3つの質問:

  1. これはどのように作動しますか?DataContextが破棄された後も、破棄されたオブジェクトが結果をデータベースに照会するにはどうすればよいDataContextですか?
  2. 実際には何をしDispose()ますか?
  3. を処分する必要はないと聞いたことがありますが (たとえば、この質問DataContextを参照してください) 、それは悪い考えではないというのが私の印象です。DbLinq を処分しない理由はありますDataContextか?
4

3 に答える 3

3

1これはどのように機能しますか?DataContextが破棄された後でも、破棄されたDataContextはどのようにしてデータベースに結果を照会できますか?

動作しません。あなたが私たちに見せていない何かがあります。リポジトリクラスがDataContext適切に/適切なタイミングで破棄されないかToList()、すべてのクエリの最後に機能的に書き込みを行っているため、通常のクエリ変換と遅延実行が完全に無効になっていると思います。

テストアプリで次のコードを試してください。次のコードがスローされることを保証しObjectDisposedExceptionます。

// Bad code; do not use, will throw exception.
IEnumerable<Person> people;
using (var context = new TestDataContext())
{
    people = context.Person;
}
foreach (Person p in people)
{
    Console.WriteLine(p.ID);
}

これは可能な限り最も単純な再現可能なケースであり、常にスローされます。一方、people = context.Person.ToList()代わりに書く場合、クエリ結果はすでにブロックに列挙されていusingます。これは、あなたの場合に起こっていることだと思います。

2 Dispose()は実際に何をしますか?

特に、が破棄されたことを示すフラグを設定します。このフラグDataContextは、後続のすべてのクエリでチェックされ、メッセージとともにDataContextをスローします。ObjectDisposedExceptionObject name: 'DataContext accessed after Dispose.'.

DataContextまた、接続を開いたままにしておくと、接続も閉じます。

3 DataContextを破棄する必要はないと聞きましたが(たとえば、この質問を参照)、それは悪い考えではないという印象がありました。LinqToSql DataContextを破棄しない理由はありますか?

それ他のすべてに必要であるようDisposeに、DataContextに必要です。を破棄しないと、接続がリークする可能性があります。コンテキストは、実装する作業単位パターンの内部IDキャッシュを維持するため、から取得したエンティティのいずれかが存続している場合は、メモリをリークする可能性もあります。しかし、これが当てはまらなかったとしても、メソッドが内部で何をするかはあなたの関心事ではありません。それが何か重要なことをしていると仮定します。DisposeIDisposableDataContextDataContextDispose

IDisposableは、「クリーンアップは自動ではない可能性があります。終了したら私を処分する必要があります」という契約です。忘れた場合にオブジェクトがクリーンアップする独自のファイナライザーを持っているかどうかの保証はありませんDispose。実装は変更される可能性があるため、明示的な仕様ではなく、観察された動作に依存することはお勧めできません。

IDisposable空のメソッドでを破棄した場合に発生する可能性のある最悪の事態Disposeは、数CPUサイクルを浪費することです。重要な実装でを破棄しなかった場合に発生する可能性のある最悪の事態は、リソースをリークすることです。ここでの選択は明らかです。が表示された場合は、廃棄することを忘れないでください。IDisposableIDisposable

于 2010-05-17T19:58:08.017 に答える
0

"persons" は IEnumerable コレクションであり、DataContext (リポジトリ) は .GetNew 呼び出しを行うためにのみ必要です。

from/select/etc キーワードは、System.Linq 名前空間に追加された拡張メソッドのシンタックス シュガーです。これらの拡張メソッドは、DataContext ではなく、クエリで使用している IEnumerable 機能を追加します。実際、デモ用の IEnumerable をプログラムで作成することにより、LINQ2SQL をまったく使用せずにこれらすべてを実行できます。

これらのオブジェクトを使用してさらにリポジトリ (DataContext) 呼び出しを行おうとすると、エラーが発生します。

IEnumerable コレクションには、リポジトリからのすべてのレコードが含まれます。これが、クエリを作成するために DataContext を必要としない理由です。

拡張メソッド: http://msdn.microsoft.com/en-us/library/bb383977.aspx

LINQ 拡張メソッド: http://msdn.microsoft.com/en-us/library/system.linq.enumerable_members.aspx

于 2010-05-17T18:49:48.657 に答える
0

API の奥深くに、おそらく次のような API を使用するメソッドが表示されます。

http://msdn.microsoft.com/en-us/library/y6wy5a0f(v=VS.100).aspx

コマンドが実行されると、関連する DataReader オブジェクトが閉じられると、関連する Connection オブジェクトが閉じられます。

于 2010-05-17T19:01:00.157 に答える