DataContextでDispose()を呼び出した後、DBLINQクエリを列挙することができるのはなぜですか?
質問
アップデート - 答えは、明らかにdblinqが実装していないことです Dispose()
ちゃんと。 d'oh!
以下はあらゆる種類の誤解を招くものです - 最終的な行: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>
}
}
このメソッドはanを返します 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()
設定後すぐに呼び出されます persons
, 、それはです IEnumerable<Person>
, 、それがそれが呼ばれる唯一の時間です。
だから、3つの質問:
- これはどのように作動しますか?どのように処分できますか
DataContext
それでも、結果のデータベースを照会しますDataContext
処分されましたか? - 何をしますか
Dispose()
実際にやりますか? - 私はそれが必要ではないと聞いた(例を参照 この質問)aを処分する
DataContext
, 、しかし、私の印象は、それは悪い考えではないということでした。理由はありますか いいえ dblinqを処分するDataContext
?
解決
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
投げる ObjectDisposedException
メッセージで Object name: 'DataContext accessed after Dispose.'.
また、接続を閉じます DataContext
それを開いて、開いたままにしました。
3 DatAcontextを処分することは必要ではないと聞いたことがありますが、私の印象はそれが悪い考えではないということでした。 linqtosql datacontextを処分しない理由はありますか?
それ は に必要です Dispose
DataContext
, 、必要なように Dispose
ほかのすべての IDisposable
. 。処分に失敗した場合、潜在的にリーク接続が可能になる可能性があります DataContext
. 。から取得されたエンティティのいずれかがメモリを漏らすこともできます DataContext
コンテキストは、それが実装するワークパターンの内部アイデンティティキャッシュを維持するため、生き続けます。しかし、たとえそうでなくても、 それはあなたの心配ではありません 何 Dispose
メソッドは内部的に行われます。それが何か重要なことをしていると仮定します。
IDisposable
aです 契約する 「クリーンアップは自動ではないかもしれません。終了したら私を処分する必要があります。」オブジェクトに忘れてしまった場合にクリーンアップする独自のファイナルライザーがあるかどうかを保証しません Dispose
. 。実装は変更される可能性があるため、明示的な仕様とは対照的に、観察された動作に依存することは良い考えではありません。
あなたが処分した場合に起こる可能性のある最悪のこと IDisposable
空の Dispose
方法は、いくつかのCPUサイクルを無駄にすることです。あなたの場合に起こる可能性のある最悪のこと 不合格 処分する IDisposable
とともに 非自明の実装 それはあなたがリソースをリークするということです。ここでの選択は明らかです。あなたが見たら IDisposable
, 、それを処分することを忘れないでください。
他のヒント
「Persons」はIENumerableコレクションであり、DataContext(リポジトリ)は.getNew Callを行うためにのみ必要です。
from/select/etcキーワードは、system.linq namespaceに追加された拡張メソッドの構文砂糖です。これらの拡張メソッドは、datacontextではなく、クエリで使用しているienumerable機能を追加します。実際、実証するためにINumerableをプログラム的に作成することにより、LINQ2SQLをまったく使用せずにこのすべてを実行できます。
これらのオブジェクトを使用してさらにリポジトリ(dataContext)を呼び出しようとすると、エラーが表示されます。
iNumerableコレクションには、リポジトリからのすべてのレコードが含まれます。これが、クエリを作成するためにdataContextを必要としない理由です。
拡張方法: http://msdn.microsoft.com/en-us/library/bb383977.aspx
LINQ拡張法:http://msdn.microsoft.com/en-us/library/system.linq.enumerable_members.aspx
APIの奥深くでは、おそらくこのようなAPIを使用しているメソッドが表示されます。
http://msdn.microsoft.com/en-us/library/y6wy5a0f(v=vs.100).aspx
コマンドが実行されると、関連するDataReaderオブジェクトが閉じているときに関連する接続オブジェクトが閉じられます。