在LINQ-SQL中,包装DataContext是一个using语句-优缺点

在LINQ-SQL中,包装DataContext是一个using语句-优缺点,linq,linq-to-sql,datacontext,using,Linq,Linq To Sql,Datacontext,Using,在性能、内存使用、编码的易用性、正确的操作等因素方面,有人能就在using语句中包装DataContext与不在LINQ-SQL中包装DataContext的利弊发表自己的看法吗 更新:在一个特定的应用程序中,我体验到,在不使用块包装DataContext的情况下,内存使用量会不断增加,因为没有为GC释放活动对象。在下面的示例中,如果我持有对q对象列表的引用和对q的访问实体的引用,我将创建一个不为GC发布的对象图 DBDataContext db = new DBDataContext() va

在性能、内存使用、编码的易用性、正确的操作等因素方面,有人能就在using语句中包装DataContext与不在LINQ-SQL中包装DataContext的利弊发表自己的看法吗

更新:在一个特定的应用程序中,我体验到,在不使用块包装DataContext的情况下,内存使用量会不断增加,因为没有为GC释放活动对象。在下面的示例中,如果我持有对q对象列表的引用和对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与使用

    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(); 

谢谢

与其他事物相比,创建DataContext的成本可能会很高。但是,如果您已经完成了,并且希望尽快关闭连接,那么也可以从上下文中释放任何缓存的结果。记住,不管发生什么,你都在创建它,在这种情况下,你只是让垃圾收集器知道还有更多的免费东西要处理

DataContext被设计成一个简短的使用对象,使用它,完成工作单元,走出去……这正是你使用一个使用对象所做的

因此,优势在于:

  • 快速闭合连接
  • 从dispose释放内存(内容中的缓存对象)
缺点-更多代码?但这不应该是一种威慑,您在这里正确地使用了

请看下面的Microsoft答案:

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

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


嗯,这是一个
IDisposable
,所以我想这不是个坏主意。MSFT的同事们说,他们使DataContext尽可能轻量级,以便您可以不计后果地创建它们,因此您可能不会获得太多的收益….

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

另一方面,如果您的数据层可以预期来自业务层的多个连续调用,那么您将为每个较大的调用序列重复创建/处理DataContext。不理想

我所做的是尽可能创建我的数据层对象。创建DataContext时,会创建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
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用系统配置;
命名空间人员
{
公共类人员数据:IDisposable
{
#区域数据上下文管理
/// 
///为数据库的所有数据例程创建公共datacontext
/// 
private PersonnelDBDataContext_data=null;
私人人员数据上下文数据
{
得到
{
如果(_data==null)
{
_数据=新的PersonnelDBDataContext(ConfigurationManager.ConnectionString[“PersonnelDB”].ToString());
_data.DeferredLoadingEnabled=false;//无延迟加载
//var dlo=new DataLoadOptions();//数据加载选项位于此处
}
返回数据;
}
}
/// 
///关闭数据上下文
/// 
公共空间处置()
{
如果(_data!=null)
_data.Dispose();
}
#端区
#区域DL方法
公共人物GetPersonByID(字符串用户ID)
{
返回Data.Persons.FirstOrDefault(p=>p.UserID.ToUpper().Equals(UserID.ToUpper());
}
公共列表GetPersonsByIDlist(列表用户IDList)
{
var ulist=useridlist.Select(u=>u.ToUpper().Trim()).ToList();
返回Data.Persons.Where(p=>ulist.Contains(p.UserID.ToUpper()).ToList();
}
//更多方法。。。
#端区
}
}

在一个特定的应用程序中,我体验到,如果不将
DataContext
包装在
using
块中,内存使用量会不断增加,因为没有为GC释放活动对象。在下面的示例中,如果我持有对
List
对象的引用并访问
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,因为列表变量
qs
**中的所有
实例都共享相同的datacontext。在
Dispose()
之后,访问
进程(表q)
中的实体会抛出一个datacontext已处理的异常

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

根据我的经验,我会说使用
using
语句

  • 第一次DataContext将从DB获取对象
  • 下次启动查询以获取相同的对象(相同的参数):您将在探查器中看到查询,但DataContext中的对象不会被DB中的新对象替换 更不用说,在每个DataContext后面都有您从DB请求的所有对象的标识映射(您不想保留这个)

    DataContext的整个概念是工作单元,具有乐观并发性。 用于短期交易(仅一次提交)和处置


    不要忘记dispose的最好方法是使用()。

    显然,我们听到过关于创建DataContext的复杂性的不同说法。@James-虽然它没有那么重,但相对于其他东西来说,在我的c