DataReader内存泄露问题(要考虑内存)

论文MVP网 2009-03-31 02:55:16
大家听我说,我这个问题不是问DATAREADER怎么用?而是我做的程序是在内存比较少的机器上运行(PDA),为了对那些对PDA不了解的人我解释下,你们可以理解成一个内存只有16M的普通电脑,他上面还有个数据库,所以大家要解决的是DATAREADER用法有问题造成的内存泄露,说白了就是帮我看下我的写法那里存在问题,然后告诉我下我怎么达到效果是标准写法:代码如下:


SqlDataReader dr=SqlCeHelper.ExecuteReader(select * from biao1 where di1lie='2')
if(dr.Read())
{
SqlDataReader dr1=SqlCeHelper.ExecuteReader(select * form biao2 where di1lie='"+dr[0].tostring()+"')
if(dr1.Read())
{
SqlDataReader dr2=SqlCeHelper.ExecuteReader(select * from biao3 where di2lie='"+dr1[0].tostring+"');
dr1.close();
if(dr2.Read())
{
SqlDataReader dr3=SqlCeHelper.ExecuteReader(select * from biao4 where di3lie='"+dr2[0].tostring+"');
if(dr3.read())
{
MessageBox.show("类似于这样的循环有4,5层左右");
dr3.close();
}
}
dr2.close();
}
dr.close();

}
else
{
dr.close();
}






就类似于这样的查询方法,查询出来一个数据然后直接把这个数据作为下一个查询的查询参数,然后再查出来一个数,再做为下一个查询的参数,由于我用的是SQLCE数据库(你不用会SQLCE数据库,只要知道他不支持select * from (select * from b)就可以了)所以我一层层的嵌套,由于我的程序会不定时死机,所以我想咨询下这种嵌套写法是正确,是否有问题? 如果有问题怎么解决?我都已经在每个关键的地方dr.close()了,但是最后还不行还是有死机情况,是不是DATAREADER的问题?着急,谢谢,不会的帮顶,不会的不要乱答,帮顶就行,注意回帖质量
...全文
214 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
论文MVP网 2009-04-01
  • 打赏
  • 举报
回复
算了 看来你们都没亲自做过,像你们一直做WINFORM或者WEB程序根本不会碰到这个问题,因为庞大的内存足够你们在使用完电脑之前通过关机来自动清理,我昨天写了一晚上暂时算是知道结果了,不过今天还需要测试一天才能知道,
我说下答案,
DATAREADER 在内存只能存在一个,使用完后必须立刻释放当前连接也就是DR.CLOSE()来关闭掉,而不能他还没关闭(dr.close)咋们就调用另一个datareader ,这在语法上是正确的,而且程序百分之百不会报错,因为你在桌面电脑上做程序完全足够,根本没必要考虑到这个问题,因为内存现在基本都1G左右,足够你们用的了,但是我是在PDA上做程序,内存只有15左右,所以开的DATAREADER嵌套的话肯定不够用!

总结 DATAREADER使用不可以嵌套,如果需要其中的值可以赋给一个数组,然后立刻关闭,以后一直用这个数组来代替DATAREADER

DATAREADER dr=sqlhelper.excutereader("select * from biao1")
string[] drstr=new string[6]{dr[0].tostring(),dr[1].tostring}
dr.close();
datareader dr1=sqlhelper.excutereader{"select * from biao1 where drstr[0]"}
dr1.close();

这样写 即可,使用后每次立刻关闭,而不能嵌套,就是说第1个没关闭之前,不能再运行第2个DR,用完立刻关闭,可以说是不支持嵌套来总结,同时希望大家以后注意细节问题,才能写出高质量的代码,这次我都返工了,回帖注意质量,谢谢
juqiang 2009-03-31
  • 打赏
  • 举报
回复
楼主怎么判断是内存泄露的?
程序不定时死机,是什么意思?
特别 2009-03-31
  • 打赏
  • 举报
回复

SqlDataReader dr=SqlCeHelper.ExecuteReader("select * from biao1 where di1lie='2'");
if(dr.Read())
{
SqlDataReader dr1=SqlCeHelper.ExecuteReader("select * form biao2 where di1lie='"+dr[0].tostring()+"'")
if(dr1.Read()) //如果dr1没有数据,dr1将关闭不了
{
SqlDataReader dr2=SqlCeHelper.ExecuteReader("select * from biao3 where di2lie='"+dr1[0].tostring+"'");
dr1.close();
if(dr2.Read())
{
SqlDataReader dr3=SqlCeHelper.ExecuteReader("select * from biao4 where di3lie='"+dr2[0].tostring+"'");
if(dr3.read()) //如果dr3没有数据,dr3将关闭不了
{
MessageBox.show("类似于这样的循环有4,5层左右");
dr3.close();
}
}
dr2.close();
}
dr.close();

}
else
{
dr.close();
}

可以改成

SqlDataReader dr=SqlCeHelper.ExecuteReader("select * from biao1 where di1lie='2'");
if(dr.Read())
{
SqlDataReader dr1=SqlCeHelper.ExecuteReader("select * form biao2 where di1lie='"+dr[0].tostring()+"'")
if(dr1.Read()) //如果dr1没有数据,dr1将关闭不了
{
SqlDataReader dr2=SqlCeHelper.ExecuteReader("select * from biao3 where di2lie='"+dr1[0].tostring+"'");

if(dr2.Read())
{
SqlDataReader dr3=SqlCeHelper.ExecuteReader("select * from biao4 where di3lie='"+dr2[0].tostring+"'");
if(dr3.read()) //如果dr3没有数据,dr3将关闭不了
{
MessageBox.show("类似于这样的循环有4,5层左右");

}
dr3.close();

}
dr2.close();
}
dr1.close();

}

dr.close();
jie3614 2009-03-31
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 ojekleen 的回复:]
这代码写的。。。。
SqlCeHelper.ExecuteReader的封装方法贴出来看看。
你关闭reader,不一定关系了conntection

你不用会SQLCE数据库,只要知道他不支持select * from (select * from b)就可以了,难道多表查询都不支持?

select * from biao1 ,biao2 where biao1.di1lie=biao2.id(这个不知道你的第一列是什么字段。) and bi1lie='2';
[/Quote]

顶一个 楼主这样查询多次很消耗资源的 多表查询效率高 另外楼主这儿用dr.Dispose();试试
zzxap 2009-03-31
  • 打赏
  • 举报
回复
dr及時覆蓋掉
gucheng2008 2009-03-31
  • 打赏
  • 举报
回复
把查询的数据放到dataset或者datatable里边吧,这样好像是不行
zzxap 2009-03-31
  • 打赏
  • 举报
回复
[code=C#]
試試這樣的
STRING stra=""
STRING strb=""
STRING strc=""

SqlDataReader dr=SqlCeHelper.ExecuteReader(select * from biao1 where di1lie='2')
if(dr.Read())
{ stra=dr1[0].tostring

SqlDataReader dr=SqlCeHelper.ExecuteReader(select * form biao2 where di1lie='"+stra+"')
if(dr.Read())
{ strb=dr[0].tostring
SqlDataReader dr=SqlCeHelper.ExecuteReader(select * from biao3 where di2lie='"+strb+"');
//dr.close();
if(dr.Read())
{ strc=dr[0].tostring
SqlDataReader dr=SqlCeHelper.ExecuteReader(select * from biao4 where di3lie='"+strc+"');
if(dr.read())
{
MessageBox.show("类似于这样的循环有4,5层左右");
dr.close();
}
}
// dr2.close();
}
//dr.close();

}
else
{
dr.close();
}



[/CODE]
linaren 2009-03-31
  • 打赏
  • 举报
回复
内存泄露可能是在连接上的
linaren 2009-03-31
  • 打赏
  • 举报
回复
你这种写法就是在执行完全部过程后才释放dr的,为什么不查询完就close呢比如:
SqlDataReader dr=SqlCeHelper.ExecuteReader(select * from biao1 where di1lie='2')
string var1="";
if(dr.Read())
{
var1= dr[0].tostring();
}
dr.close();
if (!"".equal(var1)){
...
...
...
}
ojekleen 2009-03-31
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 zzxap 的回复:]
2樓是錯的,
dr不用的時候 dr=nothing


[/Quote]
dr=null;内存照样回收不急时的,
这个很显然的多表查询问题,不可能这样写查询语句的,,,如果多表查询都不支持的话,那还是关系数据库?

zhoulehua 2009-03-31
  • 打赏
  • 举报
回复
等待高手了。
zzxap 2009-03-31
  • 打赏
  • 举报
回复
2樓是錯的,
dr不用的時候 dr=nothing

zzxap 2009-03-31
  • 打赏
  • 举报
回复
[code=C#]
SqlDataReader dr=SqlCeHelper.ExecuteReader(select * from biao1 where di1lie='2')
if(dr.Read())
{
SqlDataReader dr=SqlCeHelper.ExecuteReader(select * form biao2 where di1lie='"+dr[0].tostring()+"')
if(dr.Read())
{
SqlDataReader dr2=SqlCeHelper.ExecuteReader(select * from biao3 where di2lie='"+dr[0].tostring+"');
dr.close();
dr=nothing;
if(dr2.Read())
{
SqlDataReader dr=SqlCeHelper.ExecuteReader(select * from biao4 where di3lie='"+dr2[0].tostring+"');
if(dr.read())
{
MessageBox.show("类似于这样的循环有4,5层左右");
dr.close();
}
}
dr2.close();
}
dr.close();

}
else
{
dr.close();
}

[/CODE]

ojekleen 2009-03-31
  • 打赏
  • 举报
回复
这代码写的。。。。
SqlCeHelper.ExecuteReader的封装方法贴出来看看。
你关闭reader,不一定关系了conntection

你不用会SQLCE数据库,只要知道他不支持select * from (select * from b)就可以了,难道多表查询都不支持?

select * from biao1 ,biao2 where biao1.di1lie=biao2.id(这个不知道你的第一列是什么字段。) and bi1lie='2';
1. C#语言方面... 4 1.1 垃圾回收... 4 1.1.1 避免不必要的对象创建... 4 1.1.2 不要使用空析构函数 ★... 4 1.1.3 实现 IDisposable 接口... 4 1.2 String 操作... 5 1.2.1 使用 StringBuilder 做字符串连接... 5 1.2.2 避免不必要的调用 ToUpper 或 ToLower 方法... 5 1.2.3 最快的空串比较方法... 6 1.3 多线程... 6 1.3.1 线程同步... 6 1.3.2 使用 ThreadStatic 替代 NameDataSlot ★... 7 1.3.3 多线程编程技巧... 7 1.4 类型系统... 8 1.4.1 避免无意义的变量初始化动作... 8 1.4.2 ValueType 和 ReferenceType. 8 1.4.3 尽可能使用最合适的类型... 9 1.5 异常处理... 10 1.5.1 不要吃掉异常★... 10 1.5.2 不要吃掉异常信息★... 10 1.5.3 避免不必要的抛出异常... 10 1.5.4 避免不必要的重新抛出异常... 10 1.5.5 捕获指定的异常,不要使用通用的System.Exception. 10 1.5.6 要在finally里释放占用的资源... 11 1.6 反射... 11 1.6.1 反射分类... 12 1.6.2 动态创建对象... 12 1.6.3 动态方法调用... 12 1.6.4 推荐的使用原则... 12 1.7 基本代码技巧... 13 1.7.1 循环写法... 13 1.7.2 拼装字符串... 13 1.7.3 避免两次检索集合元素... 13 1.7.4 避免两次类型转换... 14 1.7.5为字符串容器声明常量,不要直接把字符封装在双引号" "里面。... 14 1.7.6 用StringBuilder代替使用字符串连接符 “+”. 14 1.7.7 避免在循环体里声明变量,... 15 1.8 Hashtable. 15 1.8.1 Hashtable机理... 15 1.8.2 使用HashTale代替其他字典集合类型的情形:... 16 1.9 避免使用ArrayList。... 16 1.10从XML对象读取数据... 17 1.11 避免使用递归调用和嵌套循环,... 17 1.12 使用适当的Caching策略来提高性能... 17 2. Ado.Net 17 2.1 应用Ado.net的一些思考原则... 18 2.2 Connection. 18 2.2.1 在方法中打开和关闭连接... 18 2.2.2 显式关闭连接... 18 2.2.3 确保连接池启用... 19 2.2.4 不要缓存连接... 19 2.3 Command. 19 2.3.1 使用ExecuteScalar和ExecuteNonQuery. 19 2.3.2 使用Prepare. 19 2.3.3 使用绑定变量 ★... 19 2.4 DataReader 20 2.4.1 显式关闭DataReader 20 2.4.2 用索引号访问代替名称索引号访问属性... 20 2.4.3 使用类型化方法访问属性... 20 2.4.4 使用多数据集... 20 2.5 DataSet 21 2.5.1 利用索引加快查找行的效率... 21 2. 使用DataView.. 21 3.ASP.NET. 21 3.1 减少往返行程(Reduce Round Trips)... 21 3.2 避免阻塞和长时间的作业... 22 3.3 使用缓存... 22 3.4 多线程... 22 3.5 系统资源... 23 3.6 页面处理... 23 3.7 ViewState. 23 4.JScript 24 4.1 JScript性能优化的基本原则... 24 4.2 JScript语言本身的优化... 24 4.3 DOM相关... 27 4.4 其他... 28

111,126

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧