【问题标题】:Reliably drop a database on SQL Server 2008 via C#通过 C# 在 SQL Server 2008 上可靠地删除数据库
【发布时间】:2017-05-08 06:24:06
【问题描述】:

我目前正在尝试通过以下代码删除数据库

using Microsoft.SqlServer.Management.Smo;

var server = new Server(Server);
server.KillAllProcesses("Db");
server.KillDatabase("Db");

有时它有效,但其他我得到以下异常:

Microsoft.SqlServer.Management.Smo.FailedOperationException:为服务器“Host1”杀死数据库失败。
---> Microsoft.SqlServer.Management.Common.ExecutionFailureException:执行 Transact-SQL 语句或批。
---> System.Data.SqlClient.SqlException:此时无法更改数据库“Db”的状态或选项。数据库处于单用户模式,并且当前有一个用户连接到它。

关于如何通过代码可靠地删除数据库的任何想法?

【问题讨论】:

  • 你先尝试ALTER DATABASE Db SET MULTI_USER;了吗?
  • 我个人不会为此使用 SMO,主要是因为我不知道那些 Kill...() 函数的确切作用。我宁愿说USE master; ALTER DATABASE Db SET SINGLE_USER WITH ROLLBACK IMMEDIATE; DROP DATABASE Db;
  • 默认情况下数据库未设置为 SingleUser,我认为 KillDatabase 方法的失败尝试将其转换为 Single User 然后就这样离开了。
  • 在使用 KillDatabase 时运行分析器。这就是我得到的(除其他外)。 ALTER DATABASE [Db] SET SINGLE_USER WITH ROLLBACK IMMEDIATE .... DROP DATABASE [Db]
  • 那么,究竟是如何解决的呢?我遇到了同样的问题,除了我使用 SQL Server Express 2005?从历史上看,我使用过这种方法 (stackoverflow.com/questions/5170429/…),我发现它只比Server.KillDatabase 稍微可靠一点。但是,DROP 方法也不是 100% 可靠的。康斯坦丁是如何解决这个问题的?

标签: c# sql-server-2008


【解决方案1】:

要通过 SMO 可靠地删除数据库,调用 server.KillDatabase("Db"); 就足够了。 MSDN 确实声明 KillDatabase 会丢弃活动连接,即使他们的示例有点误导。

KillDatabase 发出 ALTER DATABASE [Db] SET SINGLE_USER WITH ROLLBACK IMMEDIATE,然后是 DROP DATABASEKillAllProcesses 列出所有连接并将每个进程作为单独的批次发出一次终止;假设KillAllProcesses 是异步的,则在KillDatabase 将数据库设置为单用户模式后发生kill 时将引发异常。

【讨论】:

    【解决方案2】:

    在我的情况下,我得到的错误是通过在 KILL 方法之前添加 server.Databases.Refresh 来修复的。原因是我试图删除的数据库是在实例化服务器对象之后创建的,换句话说,我是临时创建一个数据库,从中提取数据并删除它。数据库未显示在数据库(对象)列表中。添加刷新就可以了...

    【讨论】:

      【解决方案3】:

      我有错误(“drop failed...”) 使用 MSDN:

      dbServer.KillAllProcesses(db.Name);
      dbServer.KillDatabase(db.Name);
      

      解决方法是:

      string sqlCommandText = @"USE master; 
      ALTER DATABASE [" + db.Name + "] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; 
      DROP DATABASE [" + db.Name + "]";  
      dbServer.ConnectionContext.ExecuteNonQuery(sqlCommandText);
      

      【讨论】:

        【解决方案4】:

        我通过在没有池的情况下创建 ServerConnection 来修复此类错误。像这样:

        var serverConnection = new ServerConnection(serverName)
        {
             ...,
             NonPooledConnection = true
        };
        server = new Server(serverConnection);
        server.KillAllProcesses(databaseName);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-11-17
          • 1970-01-01
          相关资源
          最近更新 更多