问题描述
publicclasssqlhelper{privatestaticSqlConnectionconn=null;//创建数据库连接对象privatestaticSqlCommandcmd=null;//创建命令对象privatestaticSqlDataReadersdr=null;//创建SQLDATAREADER对象///<summary>///打开数据库连接///</summary>///<returns></returns>privatestaticSqlConnectionGetConn(){stringconnStr=ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;conn=newSqlConnection(connStr);if(conn.State!=ConnectionState.Open){conn.Open();}returnconn;}///<summary>///执行不带参数查询SQL语句或存储过程///</summary>///<paramname="cmdText">查询SQL语句或存储过程</param>///<paramname="ct">命令类型</param>///<returns></returns>publicstaticDataTableExecuteQuery(stringcmdText,CommandTypect){DataTabledt=newDataTable();using(cmd=newSqlCommand(cmdText,GetConn())){cmd.CommandType=ct;using(sdr=cmd.ExecuteReader(CommandBehavior.CloseConnection)){dt.Load(sdr);//sdr.Close();}sdr.Close();}returndt;}///<summary>///执行带参数的查询SQL语句或存储过程///</summary>///<paramname="cmdText">查询SQL语句或存储过程</param>///<paramname="paras">参数集合</param>///<paramname="ct">命令类型</param>///<returns></returns>publicstaticDataTableExecuteQuery(stringcmdText,SqlParameter[]paras,CommandTypect){DataTabledt=newDataTable();using(cmd=newSqlCommand(cmdText,GetConn())){cmd.CommandType=ct;cmd.Parameters.AddRange(paras);using(sdr=cmd.ExecuteReader(CommandBehavior.CloseConnection)){dt.Load(sdr);//sdr.Close();}sdr.Close();}returndt;}///<summary>///执行查询单条标题记录,并返回填充的list对象///</summary>///<paramname="cmdText">查询SQL语句或存储过程</param>///<paramname="paras">参数集合</param>///<paramname="ct">命令类型</param>///<returns></returns>publicstaticList<titleinfo>ExecuteTitleDataReader(stringcmdText,SqlParameter[]paras,CommandTypect){using(cmd=newSqlCommand(cmdText,GetConn())){cmd.CommandType=ct;cmd.Parameters.AddRange(paras);titleinfostcTitleinfo=newtitleinfo();List<titleinfo>list=newList<titleinfo>();//sdr=cmd.ExecuteReader(CommandBehavior.CloseConnection);try{sdr=cmd.ExecuteReader(CommandBehavior.CloseConnection);if(sdr.Read()){stcTitleinfo.dtimeCrtTime=sdr["CreateTime"].ToString();stcTitleinfo.iTitlesID=sdr["TitlesId"].ToString();stcTitleinfo.strTitleCont=sdr["content"].ToString();stcTitleinfo.strUserName=sdr["Author"].ToString();list.Add(stcTitleinfo);returnlist;}else{returnnull;}}catch(Exceptionex){throwex;}finally{conn.Close();sdr.Close();}}}
以上是自己改的SQLHELPER.CS,网站做好了上传服务器后,出现并发性问题如下:当一个人测试的时候,网站工作正常。当多个人同时测试的时候,以上3个函数,publicstaticDataTableExecuteQuery,publicstaticDataTableExecuteQuery,publicstaticList<titleinfo>ExecuteTitleDataReader,特别容易出现如下错误“executereader要求已打开且可用的连接.连接的当前状态为正在连接”,只要多个人同时读取的页面有读取数据库操作,也就是用到以上3个函数,就会出现以上错误,感觉原因是因为SQLHELP.CS是STATIC,里面的连接变量CONN也是STATIC,所有多个人访问的是同一个连接对象,所以当同时访问时候就出现了以上错误,CONN在不同状态,想问如何更改SQLHELPER.CS来解决这个并发性问题?
解决方案
解决方案二:
///打开数据库连接///</summary>///<returns></returns>privatestaticSqlConnectionGetConn(){stringconnStr=ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;returnnewSqlConnection(connStr);//每次获取链接对象都一个新的}
解决方案三:
最好不要用datareader来读取,如果一定要用这个实体类的,每个操作完之后都要将连接对象关闭掉,也就是ExecuteTitleDataReader如这类函数,每次读完数据后要显示关闭数据库连接要不然一下就满了
解决方案四:
public static List<titleinfo> ExecuteTitleDataReader(string cmdText, SqlParameter[] paras, CommandType ct) { using (cmd = new SqlCommand(cmdText, GetConn())) { cmd.CommandType = ct; cmd.Parameters.AddRange(paras); titleinfo stcTitleinfo = new titleinfo(); List<titleinfo> list = new List<titleinfo>(); //sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection); try { sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection); if (sdr.Read()) {这里没有加using 还有一点,单条记录有必要用List?
解决方案五:
privatestaticSqlConnectionconn=null;//创建数据库连接对象privatestaticSqlCommandcmd=null;//创建命令对象privatestaticSqlDataReadersdr=null;//创建SQLDATAREADER对象
这些不能用静态成的。
解决方案六:
目前按照1楼和4楼方法,已经解决并发问题,谢谢!想请问2楼为什么“最好不要用datareader来读取”,我现在脑子里面的思路是尽量用DATAREADER啊,因为它读取记录快,而且读取后不占用内存,不需要用如DATATABLE什么的装数据。什么是显示关闭数据库连接啊?不是这样就行了吗?sdr=cmd.ExecuteReader(CommandBehavior.CloseConnection);括号的东西会在语句执行完后关闭数据库啊,难道还需要自己关闭数据库吗?3楼说的第一个地方我改了,加了USING,但是提出的第二个问题,我有点疑问:确实是单挑记录啊,如果不用LIST,怎么把单挑记录的所有数据返回呢?用什么变量装啊,我试过直接返回SDR,数据不对,又不想用DATATABLE占用内存,所以用了个结构体变量装了返回,主程序接受,感觉会节省点内存啊。不知道您说有什么考虑?
解决方案七:
publicstatictitleinfoExecuteTitleDataReadertitleinfo这个不能直接返回?
解决方案八:
对了,最近在查询SQLHELPER.CS各种代码时候,还有一个问题不懂,就如下:“返回DataReader时,是不可以用using()的”好多SQLHELPER.CS中都提到上面的一句话,我想问为什么?
解决方案九:
liuchaolin谢谢,按照你说的用titleinfo方法返回,主程序用这个结构体接受没问题。
解决方案十:
在sqlhelper.cs类中,对SqlDataReader的操作时不能用using的,只能用try-catch,方法返回SqlDataReader对象,带调用它的DAL层用using(SqlDataReadersdr=....){....}
解决方案十一:
SqlDataReader读取数据时基于游标一行一行断开式读取的,如果是用using的话,数据还没读完,连接资源都被释放了还读个毛线啊
解决方案十二:
9楼的最后一句话没搞懂什么意思啊?“带调用它的DAL层用using(SqlDataReadersdr=....){....}”是什么意思啊,就是说我这列中的像3楼说的那样可以加个USING把SQLDATAREADERSDR=...包起来吗?
解决方案十三:
感觉6楼说的和10楼说的用USING的地方正好矛盾啊。。。。不是很理解。。。,求解释
解决方案十四:
程序开发的真谛,最起码地,就是需要特意测试并发情况下的bug。我不想关系你的代码,只想提醒你,凡是刚刚才醒悟到“要考虑并发冲突”的人一定是刚刚上课没有好好听老师的讲解,需要自己主动补课。
解决方案十五:
你应该自己搞明白出现bug的原理。你这个程序,还设计个privatestaticSqlDataReadersdr=null
这不是明摆着的嘛。
解决方案:
至于另外两个static,也是一样。更多的代码,懒得看了。只看前几行,就可以扔掉这个SQLHelper了。
解决方案:
自学的ASP.NET的,所以有些地方不是很清楚
解决方案:
这个并发的问题已经解决了哦,现在在看SQLDATAREADER能不能用USING,感觉6楼和10楼说的有点矛盾。。。。
解决方案:
"流氓会演讲谁也挡不住"我以后发帖,你不要插嘴,每次都是进去一顿乱骂,或者乱讲,解决不了屁问题,滚你妈,你名字取的真好了,好多次了,总是问东,你就答西搞的自己很牛逼一样,我知道有问题才问,你说丢掉SQLHERLPER.CS,问题没搞清楚就去下载一个别人的用???,我知道自己是菜鸟,我测试出了问题,不知道怎么解决,请教一下怎么了????我也不是没测试,找不到问题就乱问,现在问,只是为了以后能更好的处理问题,你不知道就别乱讲,让我和别人讨论不行???????记住以后我的帖子你不要回不要进来,我现在找我的好多帖子都是你在乱讲,搞的自己很高深,而实际问题一点都没解决。不信你自己看下面几个链接,你放的狗屁:http://bbs.csdn.net/topics/390665803http://bbs.csdn.net/topics/390228505http://bbs.csdn.net/topics/390694526没有一个能解决实际问题,没一个能打到点子上,总是问东答的不知道是哪里,装B干什么,都是搞技术的,你再看看这些帖子里面我给分的,人家是怎么回答的,光我才10几个帖子了,你都来装,其他我就不说了,记住以后我的帖子,你别来,来了别说话,看别人怎么讨论指导的,你来了千万别放屁!!!!!!!!!!!!
解决方案:
第二行privatestaticSqlConnection往后都不用看了
解决方案:
声明为static,就像几个人同时用一个茅坑,你看会出问题不
解决方案:
引用11楼PPWD_PPWD的回复:
9楼的最后一句话没搞懂什么意思啊?“带调用它的DAL层用using(SqlDataReadersdr=....){....}”是什么意思啊,就是说我这列中的像3楼说的那样可以加个USING把SQLDATAREADERSDR=...包起来吗?
在sqlhelper中不能用using包起来,说实在的,你应该去看看SqlDataReader的原理,你就知道哪里改用哪里不该用了
解决方案:
21楼你说的第一句就错了啊,在SQLHELPER中不能用USING么?
解决方案:
19楼的鸟人,没要你看,滚!
解决方案:
引用23楼PPWD_PPWD的回复:
19楼的鸟人,没要你看,滚!
CSDN可不是你的狗窝,轮不到你这样撒野
解决方案:
鉴于很久之前犯过同样的错误咱把错误的地方告诉与你,真是好心没好报
解决方案:
引用5楼PPWD_PPWD的回复:
目前按照1楼和4楼方法,已经解决并发问题,谢谢!想请问2楼为什么“最好不要用datareader来读取”,我现在脑子里面的思路是尽量用DATAREADER啊,因为它读取记录快,而且读取后不占用内存,不需要用如DATATABLE什么的装数据。什么是显示关闭数据库连接啊?不是这样就行了吗?sdr=cmd.ExecuteReader(CommandBehavior.CloseConnection);括号的东西会在语句执行完后关闭数据库啊,难道还需要自己关闭数据库吗?3楼说的第一个地方我改了,加了USING,但是提出的第二个问题,我有点疑问:确实是单挑记录啊,如果不用LIST,怎么把单挑记录的所有数据返回呢?用什么变量装啊,我试过直接返回SDR,数据不对,又不想用DATATABLE占用内存,所以用了个结构体变量装了返回,主程序接受,感觉会节省点内存啊。不知道您说有什么考虑?
DataReader只能前进,不能后退,Reader用完之后必须关闭,否则会出现问题。综上所述,最好不要使用Reader
解决方案:
引用22楼PPWD_PPWD的回复:
21楼你说的第一句就错了啊,在SQLHELPER中不能用USING么?
在使用SqlDataReader的时候在SqlHelper中不要用using,如果用了,你在后面调用该方法的时候你就知道错了,当然,除此之外,是可以用using的
解决方案:
引用16楼PPWD_PPWD的回复:
自学的ASP.NET的,所以有些地方不是很清楚
其实MSDN上面都有,楼主可以好好对比下ADO.NET的几大对象
解决方案:
privatestaticSqlConnectionconn=null;//创建数据库连接对象privatestaticSqlCommandcmd=null;//创建命令对象privatestaticSqlDataReadersdr=null;问题出在static这里,删掉应该可以了
解决方案:
或许没表述清楚,不是sqlhelper不能用using,应该说在方法返回SqldataReader的时候,该方法内部不要用using
解决方案:
引用28楼a01589的回复:
Quote: 引用16楼PPWD_PPWD的回复:
自学的ASP.NET的,所以有些地方不是很清楚其实MSDN上面都有,楼主可以好好对比下ADO.NET的几大对象
正解,上MSDN看看,或许没现在这样纠结了