简体   繁体   English

在C#中强制关闭oracle连接

[英]Force closing an oracle connection in C#

I have a report window which shows the results returned from a potentially long running oracle stored procedure. 我有一个报告窗口,其中显示了从可能长时间运行的oracle存储过程返回的结果。 My problem is when the user closes the window the connection to oracle remains open and the potentially long running report doesn't get cancelled. 我的问题是,当用户关闭窗口时,与oracle的连接保持打开状态,并且可能长时间运行的报告不会被取消。

The only way to close the open connection is for either the DBAs to kill them manually or for the user to exit the entire application. 关闭打开的连接的唯一方法是让DBA手动杀死它们或让用户退出整个应用程序。

I've tried calling Close on the connection from a different thread, but this seems to continuously block. 我尝试从另一个线程在连接上调用Close ,但这似乎一直处于阻塞状态。 I also tried rolling back a transaction, but this exhibits the same problem. 我还尝试回滚事务,但这也存在相同的问题。

I'm worried that the only solution will be to run the query in a different process (or maybe app domain?). 我担心唯一的解决方案是在不同的过程(或应用程序域?)中运行查询。

It's likely that I'm missing something obvious, any help would be greatly appreciated. 我很可能缺少明显的东西,任何帮助将不胜感激。

PLEASE READ 请阅读

This question is not about wrapping my connection in a using statement. 这个问题不是关于将我的连接包装在using语句中。 It is about how to force an oracle connection that is executing a query to close . 关于如何强制执行查询的oracle连接关闭

Example: 例:

  • Start a thread running a query 启动运行查询的线程
  • Stash the connection object somewhere 将连接对象藏在某处
  • Call close on the connection object 在连接对象上调用关闭

     public void Go() { OracleConnection connection; var queryThread = new Thread( () => { using (connection = OpenOracleConnection()) { // execute stored proc that takes 45 mins // raise an event with the data set we load } }); Thread.Sleep(3000); // give it time to be useless var closeThread = new Thread( () => { connection.Close(); }); closeThread.Start(); } 

The problem is that this doesn't close the connection, instead the call to connection.Close() blocks waiting for the procedure to execute. 问题在于这不会关闭连接,而是对connection.Close()的调用会阻止等待过程执行。

Hm, I can't see anything in the API to abort / cancel an ongoing query . 嗯,我看不到API中的任何内容来终止/取消正在进行的查询。 Technically it should be possible, with a second session with full privileges, to identify the session you want to abort and issue the kill session command on that session. 从技术上讲,应该可以使用第二个具有完全特权的会话来标识要中止的会话,并在该会话上发出kill session命令。 I would expect your original session to bail out with some kind of exception, but I've never tried it out. 我希望您的原始会话可以通过某种方式纾困,但我从未尝试过。

Here it is explained how to kill a session. 这里说明了如何终止会话。

Here it is answered how to get the session id. 在这里回答如何获取会话ID。 You could find that one out before starting the long running query, then it should be pretty easy to kill exactly that session from a second connection. 您可以在开始长时间运行的查询之前找到一个会话,然后从第二个连接中确切终止该会话应该很容易。

Let us know if it works ;) 让我们知道它是否有效;)

To see what/who is blocking who: 要查看什么/谁阻止了谁:

select s1.username || '@' || s1.machine
   || ' ( SID=' || s1.sid || ' )  is blocking '
   || s2.username || '@' || s2.machine || ' ( SID=' || s2.sid || ' ) ' AS status
   from v$lock l1, v$session s1, v$lock l2, v$session s2
   where s1.sid=l1.sid and s2.sid=l2.sid
   and l1.BLOCK=1 and l2.request > 0
   and l1.id1 = l2.id1
   and l2.id2 = l2.id2;

As with any provider in .NET you can call Dispose 与.NET中的任何提供程序一样,您可以调用Dispose

using(var conn = /* your connection */) {
    // do your stuff

    conn.Close();
} // this will automatically call .Dispose()

So that is all you need to do. 这就是您需要做的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM