简体   繁体   English

数据库删除后,Sql Server 2008关闭连接

[英]Sql Server 2008 Closing Connections after database dropped

I am having problems with SQL Server dropping a connection after I have dropped and re-created a given database and the next time I try to execute a command against a new connection on that same database, I get: 在删除并重新创建给定数据库之后,我遇到SQL Server丢弃连接的问题,下次当我尝试对同一个数据库上的新连接执行命令时,我得到:

A transport-level error has occurred when sending the request to the server. 将请求发送到服务器时发生传输级错误。 (provider: Shared Memory Provider, error: 0 - No process is on the other end of the pipe.) (提供者:共享内存提供者,错误:0 - 管道的另一端没有进程。)

Here is the TCP version (If I try connecting to another server) 这是TCP版本(如果我尝试连接到另一台服务器)

A transport-level error has occurred when sending the request to the server. 将请求发送到服务器时发生传输级错误。 (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.) (提供程序:TCP提供程序,错误:0 - 远程主机强制关闭现有连接。)

Here are the steps to repro the problem: 以下是重现问题的步骤:

  1. Open a connection to a database and execute a sql command 打开与数据库的连接并执行sql命令
  2. Drop the database 删除数据库
  3. Re-Create the database 重新创建数据库
  4. Open a new connection to the same database and attempt to run a command against it 打开与同一数据库的新连接,并尝试对其运行命令

Result: I receive an exception 结果:我收到一个例外

Here is the Code: 这是代码:

using (var conn = new System.Data.SqlClient.SqlConnection("Data Source=.;Initial Catalog=DBNAME;Integrated Security=True"))
{
    conn.Open();
    var cmd = conn.CreateCommand();
    cmd.CommandText = "UPDATE ...";
    cmd.ExecuteNonQuery();
}

string sql = "Alter Database DBNAME set single_user with rollback immediate drop database DBNAME";
var server = new Microsoft.SqlServer.Management.Smo.Server(".");
server.ConnectionContext.ExecuteNonQuery(sql);
server.ConnectionContext.Disconnect();

sql = File.ReadAllText("PathToDotSqlFile..."));
server = new Microsoft.SqlServer.Management.Smo.Server(".");
server.ConnectionContext.ExecuteNonQuery(sql);
server.ConnectionContext.Disconnect();

using (var conn = new System.Data.SqlClient.SqlConnection("Data Source=.;Initial Catalog=WER_CONFIG;Integrated Security=True"))
{
    conn.Open();
    var cmd = conn.CreateCommand();
    cmd.CommandText = "UPDATE ...";
    cmd.ExecuteNonQuery();
}

The error occurs on the line 'cmd.ExecuteNonQuery()' at the very end. 错误发生在最后的'cmd.ExecuteNonQuery()'行。 It appears that even though I am creating a new connection each time I connect, sql server is keeping track of something (or possibly the ADO.net code) where the next time I ask for a connection, it gives me one that is already used or has been closed on the server side. 看来即使我每次连接时都在创建一个新的连接,sql server也会记录下一次我要求连接的东西(或者可能是ADO.net代码),它给了我一个已经使用的连接或已在服务器端关闭。 It doesn't realize it was closed by the server (presumably because of the database it is connected to being dropped) until you try to execute another command against it. 它没有意识到它被服务器关闭(可能是因为数据库被连接到被丢弃),直到你尝试对它执行另一个命令。

Note that if I don't do the first step of executing the initial query, and I just drop the database, re-create it, and execute a command, I do not receive this error. 请注意,如果我没有执行初始查询的第一步,我只是删除数据库,重新创建它,并执行命令,我不会收到此错误。 I think establishing that initial connection before the database is dropped is an important part of this error. 我认为在删除数据库之前建立初始连接是此错误的重要部分。

I have also tried using an external process to drop and recreate the database like so: 我也尝试使用外部进程删除并重新创建数据库,如下所示:

ProcessStartInfo info = new ProcessStartInfo("sqlcmd.exe", " -e -E -S . -Q \"Alter Database DBNAME set single_user with rollback immediate drop database DBNAME\"");
var p = Process.Start(info);
p.WaitForExit();

info = new ProcessStartInfo("sqlcmd.exe", " -i " + PathToDotSqlFile);
p = Process.Start(info);
p.WaitForExit();

And that did not help. 这没有帮助。

Is there a way to create a new SqlConnection and ensure it is clean and not from a pool? 有没有办法创建一个新的SqlConnection并确保它是干净的而不是从池? Any other suggestions on how to solve this problem? 关于如何解决这个问题的任何其他建议?

UPDATE: Using SqlConnection.ClearPool() did solve the problem but I chose to just edit my connection string with pooling=false which also worked. 更新:使用SqlConnection.ClearPool()确实解决了问题,但我选择只使用pooling = false编辑我的连接字符串,这也是有效的。

ADO.NET automatically manages a connection pool. ADO.NET自动管理连接池。 When you "close" a connection in your application, it is returned to the pool and kept alive, in case you request a connection with the same connection string. 当您“关闭”应用程序中的连接时,如果您使用相同的连接字符串请求连接,它将返回到池并保持活动状态。 This could be the reason why your "new" connection is stale. 这可能是您的“新”连接过时的原因。

You could try to turn off this behaviour by adding pooling=false as parameter to your connection string. 您可以尝试通过将pooling=false作为参数添加到连接字符串来关闭此行为。

Don't know about SQL2008, but this sounds like a connection pooling problem on the application side. 不知道SQL2008,但这听起来像应用程序端的连接池问题。 In the old days, we added "OLEDB Services=-1" to the connection string to turn off connection pooling. 在过去,我们在连接字符串中添加了“OLEDB Services = -1”以关闭连接池。 There is probably a more elegant way to do this now. 现在可能有更优雅的方式来做到这一点。

edit: ADO.Net 2.0 seems to have added a ClearPool function to the SQLConnection object. 编辑:ADO.Net 2.0似乎已向SQLConnection对象添加了ClearPool函数。 ( http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.clearpool(VS.80).aspx ) I am very interested to know if this works. http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.clearpool(VS.80).aspx )我很想知道这是否有效。

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

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