我们知道DataContext实现了IDisposable接口。在C#中,凡是实现了IDisposable接口的类,都推荐的使用using语句。如下:

using (DataContext db = new DataContext(fileOrServerOrConnection))
{
//...
}

使用using语句可以确保以正确的方式调用Dispose方法,即使在语句块中出现异常,Dispose方法也将被执行。

但当我们使用如下代码时,将不可避免地得到“System.ObjectDisposedException: 无法访问已释放的对象”异常:

static void Main()
{
var products = GetProductByPrice(20);
foreach (var p in products)
{
// ...
}
} private static IEnumerable<Product> GetProductsByPrice(decimal price)
{
using (NorthwindDataContextDataContext db = new NorthwindDataContextDataContext())
{
var product = from p in db.Products
where p.UnitPrice >= price
select p;
return product;
}
}

由于延迟加载的特性,LINQ to SQL其实并没有真正查询数据库,而会将实际查询放到遍历时才进行(在Table.GetEnumerator方法内部调用SqlProvider的Execute方法)。而此时DataContext早已Dispose,自然无法访问。

解决此问题有两种方法:

  1. GetProductsByPrice方法返回时执行ToList方法,这将立即执行查询。
  2. 不手动Dispose。这样将会在遍历的时候执行查询。

使用方法1等于摒弃了延迟查询的优势,而使用方法2,是否会对系统造成过多的负载呢?

对此,我翻阅了一些资料,发现尽管有的支持手动Dispose的方式,但更多的则认为没有必要这么做:

我们用Reflector打开DataContext,可以看到在其Dispose方法中调用了SqlProvider的Dispose方法。而SqlProvider.Dispose方法主要任务是关闭数据库连接(调用SqlConnectionManager.DisposeConnection方法,再跟下去可以发现实际上最终是调用了SqlConnection.Close方法),剩下的无论是在DataContext还是SqlProvider的Dispose方法中,都只是将一些对象置为null。

而DataContext其实已经将数据连接的打开和关闭管理得井井有条了。在DataContext.SubmitChanges方法中可以看到,在finally块中调用了SqlConnection.Close方法。而负责执行查询的DataContext.ExecuteQuery方法跟踪到最后也会在SqlProvider.Execute方法的finally块中调用SqlConnectionManager的ReleaseConnection方法。也就是说在我们手动Dispose DataContext的时候,其实主要工作早已经执行完了,剩下的只是清空一些对象所占用的内存,使它们尽早被GC回收。除此之外,DataContext.Dispose再没有其他好处了。并且我们会发现SqlConnectionManager的ReleaseConnection方法所执行的内容甚至比CloseConnection还要多。

因此我们得出结论,在使用LINQ to SQL时,完全没有必要手动执行DataContext的Dispose方法,更没有必要使用using语句。

但是我们不禁会问,既然DataContext实现了IDisposable接口,那么为什么还要在ExecuteQuery和SubmitChanges等方法中执行资源释放的操作呢?这是否是一个设计方面的缺陷呢?欢迎您的讨论。

是否需要手动执行DataContext的Dispose方法?的更多相关文章

  1. JS魔法堂:定义页面的Dispose方法——[before]unload事件启示录

    前言  最近实施的同事报障,说用户审批流程后直接关闭浏览器,操作十余次后系统就报用户会话数超过上限,咨询4A同事后得知登陆后需要显式调用登出API才能清理4A端,否则必然会超出会话上限.  即使在页面 ...

  2. EFCore执行Sql语句的方法:FromSql与ExecuteSqlCommand

    前言 在EFCore中执行Sql语句的方法为:FromSql与ExecuteSqlCommand:在EF6中的为SqlQuery与ExecuteSqlCommand,而FromSql和SqlQuery ...

  3. crontab执行脚本中文乱码,手动执行没有问题

    crontab执行脚本中文乱码,手动执行没有问题 产生原因:       这是因为Unix/Linux下使用crontab时的运行环境已经不是用户环境了,因此原本用户下的一些环境变量的设置就失效了.例 ...

  4. 实现 Dispose 方法

    实现 Dispose 方法 MSDN 类型的 Dispose 方法应释放它拥有的所有资源.它还应该通过调用其父类型的 Dispose 方法释放其基类型拥有的所有资源.该父类型的 Dispose 方法应 ...

  5. 强制回收和IDisposable.Dispose方法

    如果某对象的 Dispose 方法被调用一次以上,则该对象必须忽略第一次调用后的所有调用. 如果对象的 Dispose 方法被多次调用,该对象一定不要引发异常. 除Dispose 之外的实例方法在资源 ...

  6. 定义页面的Dispose方法:[before]unload事件启示录

    前言 最近实施的同事报障,说用户审批流程后直接关闭浏览器,操作十余次后系统就报用户会话数超过上限,咨询4A同事后得知登陆后需要显式调用登出API才能清理4A端,否则必然会超出会话上限. 即使在页面上增 ...

  7. linux定时任务执行没结果,手动执行有结果问题总结

    今天写了个脚本手动执行有结果,但是放到系统定时任务跑却没结果,之前也遇到这种问题解决了没记录后面又懵逼了一次~~~ 如下图: 手动执行有结果 放到定时任务中每五分钟执行一次 解决方法: 脚本中加载系统 ...

  8. crontab 定时执行脚本出错,但手动执行脚本正常

    原因: crontab 没有去读环境变量,需要再脚本中手动引入环境变量,可以用source 也可以用export 写死环境变量. 为了定时监控Linux系统CPU.内存.负载的使用情况,写了个Shel ...

  9. 析构函数和Dispose方法的区别

    1. 析构函数(Finalize)只能释放非托管资源, 它是由GC调用. 2. Dispose方法可以释放托管资源和非托管资源,它是由用户手动调用的. 在Dispose()中调用 GC.Suppres ...

随机推荐

  1. eclipse打开文件位置Open Explorer 插件

    ,OpenExplorer插件可以满足这个功能,可以到https://github.com/samsonw/OpenExplorer/downloads下载最新版本,将jar包放到eclipse的pl ...

  2. asp.net mvc4中自定义404

    原文地址:http://www.chuchur.com/asp-net-mvc4-404/ 定义404 方法当然有很多种.不同的方法所展现的形式也不一样,用户所体验也不一样.以下提供2两种 方法一: ...

  3. HTML5 CSS3 诱人的实例 :模仿优酷视频截图功能

    一般的视频网站对于用户上传的视频,在用户上传完成后,可以对播放的视频进行截图,然后作为视频的展示图.项目中也可以引入这样的功能给用户一种不错的体验,而不是让用户额外上传一张展示图. 效果图: 看起来还 ...

  4. 【编译原理】语法分析LL(1)分析法的FIRST和FOLLOW集

    近来复习编译原理,语法分析中的自上而下LL(1)分析法,需要构造求出一个文法的FIRST和FOLLOW集,然后构造分析表,利用分析表+一个栈来做自上而下的语法分析(递归下降/预测分析),可是这个FIR ...

  5. 设置Eclipse启动JDK

    打开eclipse安装目录下的eclipse.ini文件,将红色内容加入 -vm ../Java/jdk1.6.0_26/bin (或者指向具体目录:D:/software/jdk_1.8u91/bi ...

  6. Spring 3.x企业应用开发实战(11)----基于@AspectJ配置切面

    1.@AspectJ的JDK必须是JDK 5.0+ 基于@AspectJ配置切面 @AspectJ采用注解描述切点.增强,两者只是表达式方式不同,效果相同. @AspectJ语法基础-----切点表达 ...

  7. ZOJ Goldbach 2013年长沙赛区网络赛

    迟到了一天的AC.... 思路: 先把单个素数 或着 两个素数能组成的情况预处理一下,然后对于给出的 n,拿第三个素数去和两个素数的情况匹配,最后要注意去重. 详情见代码. 因为手残少敲了一个 els ...

  8. windows-JDK环境变量设置

    JAVA_HOME=C:\Program Files\Java\jdk1.6.0_43;CLASS_PATH=.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar;p ...

  9. JAVA-判断请求来自PC端还是手机端

    某些情形,我们需要判断Http请求是来自手机端还是电脑端,关键是取得User-Agent的信息,进行筛选判断即可. 核心类如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ...

  10. 疯狂安卓Android自学笔记

    开发者必备自学工具: 谷歌搜索:www.yundou.info Android原版开发文档 (英文) Doc http://www.phoned.cn/docs/reference/android/v ...