2

私は MVC 2 アプリを構築しており、ストアド プロシージャで linq to sql を使用しています。

内部データ コンテキスト クラスと、アプリケーションを公開するパブリック クラスを持つデータ アクセス層を作成しました。私のパブリック クラスでは、datacontext クラスにアクセスするメソッドを公開し、linq を使用してデータを独自のオブジェクト モデル クラスに変換します。

私のパブリック クラスでは、次のパターンを使用してメソッドを公開します。

public IEnumerable<MyObject> ListObjects(int iParameter)
{
    using (MyDataContext db = new MyDataContext)
    {
        //call stored proc and convert results to my object model
        return db.List_Objects().Select(o => new MyObject()
            {
                ID = o.ID,
                Name = o.Name
                Text = o.Code + " " + o.Description
            };
    } 
} 

私の MVC アプリはモデル クラスからこのメソッドを呼び出し、aspx は結果を反復処理します。データ コンテキストの使用を using スコープ内にラップしているため、「datacontext により、Reader が閉じられているときに無効な Read の呼び出しが試行されました」というエラーが常に発生することがわかりました。using 句ですべてを scpope しなければ、問題なく動作します。どうしてこれなの?

これは必ずしもlinqまたはmvcのことではないと思います(ただし、確かにはわかりません)、using句により、すべてのオブジェクトが返される前にdisposeが呼び出されますかそれとも、列挙子がyieldの仕組みと同様に反復されているときにselect句が実行されているだけでしょうか?

4

2 に答える 2

3

Linq to Sql は、作業単位パターンを使用してデータベースへのアクセスをカプセル化します。これは、破棄 (スコープの使用の終了) 時にデータベースへの接続を閉じます。ステートメントをラップしない場合に機能する理由は、列挙時にコンテキストがまだ生きているためです。クエリ(接続が開いたままになる可能性があるため、悪い場合があります) IEnumerable、ビューまでどこかにある可能性があるを最初に使用したときにのみ実行が発生するため、スローされます。必要なのは変換ですこれIEnumerableを使用してリストに追加するToList()と、遅延するのではなくすぐに実行が強制されるため、接続が閉じられ、コレクションが作成されます。

于 2009-12-24T20:14:37.240 に答える
1

using はメソッドの呼び出しの間続くため、これがある場合:

var objects = ListObjects(123);

その後、DataContext が作成されて破棄されましたが、結果はまだ返されていません。

結果の列挙を開始すると、次のようになります。

foreach(var o in objects)

メソッド式ツリーはクエリの実行を開始しますが、データ コンテキストは既に破棄されているため、新しい接続を開くことができません。

このようなものは機能しますが、ListObject の外部からクエリを「拡張」する機能を妨げます。

public IEnumerable<MyObject> ListObjects(int iParameter)
{
    List<MyObject> objects;
    using (MyDataContext db = new MyDataContext())
    {
        //call stored proc and convert results to my object model
        objects = (db.List_Objects().Select(o => new MyObject()
            {
                ID = o.ID,
                Name = o.Name
                Text = o.Code + " " + o.Description
            }).ToList();
    } 
    return objects;
}

コンテキストを破棄するタイミングと、破棄しても問題ない場合を理解している場合は、IMO を実行しても安全です。

于 2009-12-24T20:15:41.233 に答える