代码之家  ›  专栏  ›  技术社区  ›  hIpPy

在linq-sql中,wrap the dataContext是一个using语句-pros-cons

  •  22
  • hIpPy  · 技术社区  · 15 年前

    在性能、内存使用、易于编码、正确的操作等因素方面,是否有人会在将数据上下文包装在using语句中或不包装在linq-sql中时提出自己对优缺点的看法?

    更新 : 在一个特定的应用程序中,我体验到,在不使用块包装数据上下文的情况下,随着活动对象没有为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();
        }
    

    不使用和保持活动状态的数据上下文

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

    谢谢。

    5 回复  |  直到 12 年前
        1
  •  11
  •   Nick Craver    15 年前

    与其他内容相比,数据上下文的创建成本可能很高。但是,如果你完成了它,并希望尽快关闭连接,这将做到这一点,从上下文中释放任何缓存的结果。记住,不管是什么,你都在创建它,在这种情况下,你只是让垃圾收集器知道还有更多的免费东西要处理。

    DataContext被设计成一个短期使用的对象,使用它,完成工作单元,退出……这正是您使用它所做的。

    所以优点是:

    • 快速闭合连接
    • 释放释放内存(内容中的缓存对象)

    缺点-更多代码?但那不应该是威慑,你用的是 using 这里是正确的。

    看看微软的答案: http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/2625b105-2cff-45ad-ba29-abdd763f74fe

    如果您需要使用 使用 / .Dispose() :

    简短的回答;不,你不必,但是你 应该

        2
  •  5
  •   James Curran    15 年前

    嗯,这是一个 IDisposable 所以我想这不是个坏主意。MSFT的人说,他们使数据内容尽可能的轻,这样你就可以轻率地创建它们,尽管如此,你可能不会得到太多……

        3
  •  5
  •   Vladimir Kojic    15 年前
    1. 第一次DataContext将从数据库获取对象。
    2. 下次您启动查询以获取相同的对象(相同的参数)。:您将在探查器中看到查询,但DataContext中的对象将不会替换为DB中的新对象!!

    更不用说,在每个数据上下文后面都是您从DB请求的所有对象的标识图(您不想一直这样)。

    DataContext的整个概念是 工作单位 具有 开放式并发 . 将其用于短交易(仅一个提交)和处置。

    避免忘记释放的最佳方法是使用()。

        4
  •  3
  •   Mike Jacobs    15 年前

    我取决于您的数据层的复杂性。如果每个调用都是一个简单的查询,那么每个调用都可以像在您的问题中那样包装在使用中,这样就可以了。

    另一方面,如果您的数据层可以期望业务层发出多个连续调用,那么您最终将为每个较大的调用序列重复创建/处理数据上下文。不理想。

    我所做的是将数据层对象创建为IDisposable。创建后,将创建DataContext(或在对方法进行第一次调用后创建),当数据层对象释放时,将关闭并释放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
        }
    }
    
        5
  •  1
  •   hIpPy    12 年前

    在一个特定的应用程序中,我体验到,在不包装 DataContext 在里面 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
    }
    

    在这个示例中,我无法释放DataContext,因为 所有的 Table 列表变量中的实例 qs **共享相同的数据上下文 . 后 Dispose() ,访问中的实体 process(Table q) 引发已释放的DataContext异常。

    对于我来说,丑陋的Kluge是在foreach循环之后移除q对象的所有实体引用。更好的方法当然是使用 使用 语句。

    就我的经验而言,我会说使用 使用 语句。