23

パフォーマンス、メモリ使用量、コーディングの容易さ、正しいことなどの要素の観点から、誰かがデータコンテキストをusingステートメントでラップするかLINQ-SQLでラップしないかについて、賛否両論を提案できますか?

更新ある特定のアプリケーションで、ブロックを使用する際にDataContextをラップせずに、ライブオブジェクトがGC用にリリースされなかったため、メモリ使用量が増加し続けることを経験しました。以下の例のように、qオブジェクトのリストへの参照を保持し、qのエンティティにアクセスすると、GC用にリリースされていないオブジェクトグラフを作成します。

を使用したDataContext

    using (DBDataContext db = new DBDataContext())
    {
        var q = 
            from x in db.Tables
            where x.Id == someId
            select x;

        return q.toList();
    }

使用せずに存続するDataContext

  DBDataContext db = new DBDataContext()
  var q = 
        from x in db.Tables
        where x.Id == someId
        select x;

    return q.toList(); 

ありがとう。

4

5 に答える 5

12

DataContext は、他のものに比べて、作成するのにコストがかかる場合があります。ただし、それが完了し、できるだけ早く接続を閉じたい場合は、これによりそれが行われ、キャッシュされた結果もコンテキストから解放されます。何があってもそれを作成していることを忘れないでください。この場合、ガベージコレクターに、取り除く必要のある無料のものがあることを知らせているだけです。

DataContext は、短い使用オブジェクトになるように作られています。それを使用し、作業単位を取得し、外に出します...これはまさに、使用で行っていることです。

したがって、利点:

  • より迅速に閉じられた接続
  • Dispose からメモリを解放する (コンテンツ内のキャッシュされたオブジェクト)

欠点 - コードが増える?しかし、それは抑止力にはなりませんusing。ここでは適切に使用しています。

Microsoft の回答をご覧ください: http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/2625b105-2cff-45ad-ba29-abdd763f74fe

using/を使用する必要がある場合の短いバージョン.Dispose():

短い答え; いいえ、する必要はありませんが、そうすべきです...

于 2010-02-18T21:56:33.267 に答える
5
  1. 初めて DataContext が DB からオブジェクトを取得します。
  2. 次回同じオブジェクト (同じパラメーター) を取得するためにクエリを起動するとき: プロファイラーにクエリが表示されますが、DataContext のオブジェクトは DB からの新しいオブジェクトに置き換えられません!!

言うまでもなく、すべての DataContext の背後には、DB から要求しているすべてのオブジェクトの ID マップがあります (これを維持したくないでしょう)。

DataContext の全体的な考え方は、Unit Of Work with Optimistic Concurrencyです。短いトランザクション (1 つの送信のみ) に使用し、破棄します。

dispose を忘れないようにする最善の方法は、() を使用することです。

于 2010-03-19T19:17:16.000 に答える
5

まあ、それIDisposableは悪い考えではないと思います。MSFT の人々は、DataContext を可能な限り軽量にして、無謀な放棄で作成できるようにしたと言っています。

于 2010-02-18T21:57:00.563 に答える
3

私はあなたのデータ層の複雑さに依存します。すべての呼び出しが単純な単一のクエリである場合、各呼び出しは質問のように Using でラップでき、それで問題ありません。

一方、データ レイヤーがビジネス レイヤーからの複数の連続呼び出しを予期できる場合、より大きな一連の呼び出しごとに DataContext の作成/破棄を繰り返すことになります。理想的ではありません。

私が行ったことは、データ層オブジェクトを IDisposible として作成することです。作成されると、DataContext が作成され (実際には、メソッドへの最初の呼び出しが行われると)、Data Layer オブジェクトが破棄されると、DataContext が閉じて破棄されます。

これは次のようになります。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;

namespace PersonnelDL
{
    public class PersonnelData : IDisposable
    {
        #region DataContext management
        /// <summary>
        /// Create common datacontext for all data routines to the DB
        /// </summary>
        private PersonnelDBDataContext _data = null;
        private PersonnelDBDataContext Data
        {
            get
            {
                if (_data == null)
                {
                    _data = new PersonnelDBDataContext(ConfigurationManager.ConnectionStrings["PersonnelDB"].ToString());
                    _data.DeferredLoadingEnabled = false; // no lazy loading
                    //var dlo = new DataLoadOptions(); // dataload options go here
                }
                return _data;
            }
        }

        /// <summary>
        /// close out data context
        /// </summary>
        public void Dispose()
        {
            if (_data != null)
                _data.Dispose();
        }
        #endregion

        #region DL methods
        public Person GetPersonByID(string userid)
        {
            return Data.Persons.FirstOrDefault(p => p.UserID.ToUpper().Equals(userid.ToUpper()));
        }

        public List<Person> GetPersonsByIDlist(List<string> useridlist)
        {
            var ulist = useridlist.Select(u => u.ToUpper().Trim()).ToList();
            return Data.Persons.Where(p => ulist.Contains(p.UserID.ToUpper())).ToList();
        }

        // more methods...
        #endregion
    }
}
于 2010-02-19T14:50:36.647 に答える
1

DataContextある特定のアプリケーションで、 inブロックをラップしないusingと、ライブ オブジェクトが GC 用にリリースされないため、メモリ使用量が増加し続けることがわかりました。以下の例のように、List<Table>オブジェクトへの参照を保持して のエンティティにアクセスするとq、GC 用にリリースされないオブジェクト グラフが作成されます。

DBDataContext db = new DBDataContext()
var qs = 
    from x in db.Tables
    where x.Id == someId
    select x;

return qs.toList();

foreach(q in qs)
{
    process(q);
    // cannot dispose datacontext here as the 2nd iteration 
    // will throw datacontext already disposed exception 
    // while accessing the entity of q in process() function
    //db.Dispose();
}

process(Table q)
{
    // access entity of q which uses deferred execution
    // if datacontext is already disposed, then datacontext 
    // already disposed exception is thrown
}

この例では、リスト変数**内のすべてのTableqsインスタンスが同じ datacontext を共有しているため、datacontext を破棄できません。の後Dispose()、エンティティにアクセスすると、process(Table q)すでに破棄されたデータコンテキストの例外がスローされます。

私にとって醜いクルージは、 foreach ループの後に q オブジェクトのすべてのエンティティ参照を削除することでした。より良い方法は、もちろんusingステートメントを使用することです。

私の経験によると、このusingステートメントを使用すると思います。

于 2010-03-06T16:19:02.807 に答える