目前正在与Oracle合作,但也需要一个MS SQL解决方案.
我有一个GUI,允许用户生成将在数据库上执行的SQL.这可能需要很长时间,具体取决于它们生成的搜索.我希望GUI/App在此搜索期间能够响应,我希望用户能够取消搜索.
我正在使用后台工作线程.
我的问题是,当用户取消搜索时,我无法中断对数据库的调用.它等待它完成然后,它可以轮询'CancelationPending'属性.这不仅浪费了数据库上的资源,而且还为我的代码带来了问题.
如果用户在非常长的查询中点击"搜索",则再次点击"取消",然后再次"搜索" - 第一次搜索仍然在数据库上进行搜索.后台工作人员再次点击搜索时仍然很忙.我遇到这个问题的唯一方法就是建立一个新的后台工作者.
这似乎是一种非常丑陋的做事方式.数据库继续工作我正在创建后台工作者的新实例....当我真的想要停止数据库调用并重新使用同一个worker时.
我怎样才能做到这一点?
我处理一个SqlConnection对象,但当然它并没有真正关闭.我需要关闭连接以不保持数据库对象的锁定.如何防止闭合连接锁定?
不知道的人对上述信息的解释:
关闭ADO或ADO.NET连接时,实际上并未切断与SQL Server的连接.ADO/ADO.NET基础结构可以保持连接,以防您再次使用它.这些连接在所谓的"连接池"中保持不变.
在没有使用几分钟后,连接将实际关闭.虽然,不是真的.TCP/IP有自己的方法来保持TCP连接打开几分钟(处于" CLOSE_WAIT "状态).如果您要求打开到同一IP:端口的TCP连接,则会执行此操作.如果是这样,它可以使用已经打开的TCP连接.
使用连接池和SQL Server,仍然建立与SQL Server的连接.每个连接都有一个它所在的数据库上下文.只要连接位于该数据库中:它就拥有该数据库上的共享数据库(S-DB)锁.
共享数据库锁只是意味着"请不要删除此数据库."
如何防止它在我的数据库上持有共享锁,同时保持连接池的好处?
我的ad-hoc解决方案现在每次都是开发人员调用Dispose:
connection.Dispose()
Run Code Online (Sandbox Code Playgroud)
将其更改为对全局辅助函数的调用:
Database.DisposeConnection(connection);
Run Code Online (Sandbox Code Playgroud)
它将数据库上下文更改为master:
public static void DisposeConnection(SqlConnection connection)
{
//Stop holding a database lock - in my database at least
ADOHelper.ExecuteNonQuery(connection, "USE master");
connection.Dispose();
}
Run Code Online (Sandbox Code Playgroud)
它解决了我眼前的问题; 关闭的连接没有锁定我的数据库.
但现在我担心连接池会让它的大脑混乱 - 因为我将数据库上下文切换回来.
如果有人不知道,或者不这么认为:
从SDK:
关闭和处置在功能上是等效的.
假设我们正在执行许多不同的sql命令,并且SqlCommand.CommandTimeout默认值为30秒.
让我们假设一些sql命令只是长查询,我们可能会得到超时异常.
纠正我,如果我错了,这个异常只是因为.Net不想再等了,但是如果我们使用连接池,这个连接可能会保持打开状态,那么sql语句可能仍然在SQL服务器端运行?或者这些系统之间存在一些隐藏的通信,无论我们是否使用连接池,都会突然停止它?
只是想知道什么是机制,它会影响SQL服务器的性能.我的意思是如果查询真的很长,如果它仍在运行需要10分钟才能运行它可能只会减慢服务器的速度,因为没有人能够得到结果.
UPDATE
所以这里我特别询问连接池,它肯定是代码将关闭与异常处理的连接,或者我们可以假设使用的代码是@dash在这里命名的首选模式.问题是如果我在该SqlConnection对象上调用Close()或Dispose()方法,它将返回到连接池,它不会在物理上关闭它.
我问它什么时候返回池,那个长查询仍然在SQL Server端运行.如果可能的话,如何避免这种情况.
再次更新
感谢@dash提到有关数据库事务的问题,是的,回滚将使它等待,我们没有关闭连接并将其返回到池中.那么,如果只是一个长期的选择查询或更新但只是一个单独的更新而不涉及任何数据库事务呢?特别是我想知道有没有一种方法可以告诉SQL Server我现在不需要结果请停止运行它?
我们有单元测试来测试我们的数据库安装和卸载功能是否成功运行.单元测试使用SqlClient.SqlConnection类检查之前,期间和之后的数据库内容.
我们的问题是在使用SqlClient.SqlConnection之后,卸载的drop login部分失败,因为它声称用户当前已登录.即使我们调用了SqlConnection.Close(),登录似乎仍然是打开的.
我们的代码看起来有点像这样:
InstallTables(); // function uses smo to create tables in a database.
string connString = CreateLogin("userName", "password"); // create login with smo
// Test the returned connection string connects to the database
using (SqlConnection con = new SqlConnection(connString))
{
con.Open();
//test code to read the DB version out of a table
//Dispose calls con.Close() - I have also tried calling it explicitly
}
DropTables(); // uses smo to drop tables from the database …Run Code Online (Sandbox Code Playgroud) 我已经在大学开始了近一年的网络应用程序开发.完成后,我对大学期间编写的数据库代码进行了一些更改.我在大学时使用简单的JDBC,没有使用连接池和预处理语句.在过去的一个月里,由于查询和使用的数据增加,我意识到了潜力,并且需要使用连接池和准备好的语句.
我已经实现了连接池,但没有真正注意到性能的提高.如果性能有所提高,那么我的问题就会得到解答,但是如何验证连接池和准备好的语句是否正确使用?