当前位置: 首页 > 编程语言 > C#

如何判断SqlConnection是否多了一个SqlDataReader?分享

时间:2023-04-10 15:50:51 C#

如何判断SqlConnection是否多了一个SqlDataReader?现在,这更像是一种好奇心,而不是实际目的。如果您打开一个SqlConnection并将SqlDataReader附加到它,然后尝试使用相同的SqlConnection运行另一个查询,那么它会抛出一个错误。我的问题是SqlConnection如何知道读取器是否附加到它。HasDataReader没有公共属性或任何东西,那么SqlConnection类是怎么知道的呢?原始问题:(不再相关)您好,我正在为连接池设置一些小东西和我们碰巧遇到的一个更常见的错误(它总是一个简单的修复,但我们只是不记得reader.Close()!)是当我们有一个连接被许多类/方法使用并且一个方法打开数据读取器并忘记关闭它时。这并没有那么糟糕,因为很多时候你需要做的就是进入调试器并提升一个级别并在它之前查看它并检查它是否有未关闭的数据读取器。现在,这是一个更大的问题。在这个连接池中,如果一个数据读取器是打开的,它是不可知的,直到一个线程获得连接并尝试使用它,并且最初打开数据读取器的东西可能不再存在。很简单,我如何检测数据阅读器是否在连接上打开,有没有办法在不关闭连接的情况下关闭阅读器?SqlConnection如何知道读取器是否附加到它?据我所见,SQLConnection知道它附加了一个读取器,因为它在内部维护了对它的引用。明智地使用Reflector表明SQLConnection对象具有类型为DBConnectionInternal的私有字段,该字段由该抽象类的许多具体实现之一填充。当您尝试将第二个实时阅读器添加到连接时,将在内部连接上调用方法“ValidateConnectionForExecute”,并跟踪内部“ReferenceCollection”的检查。当这显示现有的实时阅读器时会抛出异常。我想如果你愿意的话,你可以在运行时通过反射深入研究所有这些。确保数据区域(和数据库连接)关闭的方法是始终在using块中打开它们,如下所示:using(SqlDataReaderrdr=MySqlCommandObject.ExecuteReader()){while(rdr.Read()){//..}}//SqlDataReader保证在这里关闭,即使抛出异常也是如此。没有人真正回答伯爵的问题。(“你为什么要那样做?”不是答案。)我认为答案是你不能通过查看连接本身来判断连接是否有与之关联的开放数据读取器。该连接不会公开任何会告诉您的属性。打开连接会将其State属性设置为ConnectionState.Open。在其上打开数据读取器不会更改连接状态。ConnectionState.Fetching等状态值仅在SqlDataReader.Read()等数据操作正在进行时使用。当连接刚好在Reads之间时,连接状态为Open。因此,要确定打开的阅读器何时使用连接,您必须检查可能正在使用它的阅读器的状态。哇..很多人没有回答这个问题!没有人提到的是多线程应用程序。我想这里的每个人都知道你必须关闭阅读器,但我似乎没有看到任何人解决下一个请求进入时阅读器可能无法完成的事实。例如..我有一个通过单独的线程填充的表,以便我保持UI交互。在使用连接时让第二个第三个和第四个线程等待会很好。然后当它发布时做生意。如果没有一种巧妙的方法来确定连接是否连接了阅读器,我将不得不花几分钟时间为可能想要使用该连接的每个类中的每个阅读器创建一些静态布尔标志系统。比需要的复杂得多,然后尝试使用相同的SqlConnection运行另一个查询,然后它会抛出错误。当然,您可以启用多个活动结果集——这样它就不会抛出。当然有一些限制(并非总是如此?),但它会起作用。当然,这只是针对嵌套操作。如果问题是您不小心打开了某些东西(您应该关闭它),那么答案是(如前所述)使用.为了避免这种情况,将DataReader包装在一个using块中,这保证它处理这样的连接:你它的状态。检查它是否打开,如果是,请将其关闭。注意,如果您使用的是SqlHelper类,这是一个错误-在某些情况下它不会关闭连接。解决方案是在您的代码中使用try/catch或使用块,具体取决于您是否是pre-2.0版本。您还可以使用委托,如果出于任何原因您不能使用using子句,这里是一个如何实现的示例:publicdelegatevoidTransactionRunner(DbConnectionsender,DbTransactiontrans,objectstate);publicvoidRunTransaction(TransactionRunnerrunner,objectstate){RunTransaction(runner,IsolationLevel.ReadCommitted,state);}publicvoidRunTransaction(TransactionRunnerrunner,IsolationLevelil,objectstate){DbConnectioncn=GetConnectionfrompoolDbTransactiontrans=null;尝试{trans=cn.BeginTransaction(il);亚军(中国,反式,州);反式提交();}catch(Exceptionerr){if(trans!=null)trans.Rollback();抛出错误;}finally{//在这里你可以关闭任何打开的东西}}然后当你需要使用它时,只需使用该函数并将该函数作为publicvoidDoStuff(){TransactionRunnertr=newTransactionRunner(MyFunction);RunTransaction(tr,);}publicvoidDoStuffInternal(DbConnectioncn,DbTransactiontrans,objectstate){//DoStuffandImsurethatthetransactionwillcommitorrollback}这似乎是.Net3.5中的修复矫枉过正,但这就是我们当时在.Net1.0中的做法......希望它有所帮助......我今天遇到了同样的情况但是......在线运气不好所以我写了以下代码来确定我是否正在连接读者在中打开,或者一般是查找连接是否准备好使用:privateboolIsConnectionReady(SqlConnectionConnection){boolnRet=true;try{Stringsql="SELECT*FROMdummy_table";使用(SqlCommandcmd=newSqlCommand(sql,Connection)){使用(SqlDataReaderrdr=cmd.ExecuteReader()){}}}catch(Exceptionex){nRet=false;}返回nRet;“dummy_table”是我数据库中用于检查可访问性的虚拟表。这只是一种解决方法,但我应该让事情正常进行,并且在任何情况下都能够检查连接可用性。所以,我希望它能帮助你。根据这篇文章,即使您使用了using块,也应该在完成后关闭阅读器。使用块将关闭连接,但不会关闭阅读器。为什么不?愿意低头。刚刚偶然发现了这个老问题。找到一篇关于通过反思执行此操作的文章:http://blogs.msdn.com/b/dataaccesstechnologies/archive/2009/04/08/how-to-find-out-the-data-reader-referencing-an-ado-net-connection-object-to-fixmostbugsalreadythisresult-an-openDataReader-related-commandswiththisresult-which-must-be-closedfirst.aspxusingthenewlycreatedcommandobjectcreatedwith一个新的命令对象用于相同的连接和新的数据读取器。这很好用。以上就是C#学习教程:如何判断SqlConnection是否多了一个SqlDataReader?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: