C#如何检查数据库是否不忙?

我的class上有几种方法。 第一个是创建一个数据库,完成了。 然后,创建从sql文件中读取的存储过程。 然后分离那个DB。 现在看来我的存储过程查询需要一段时间才能完成,并且在数据库繁忙时调用我的分离方法。 那么我该如何判断数据库是否空闲。 例外是“无法分离数据库,因为它当前正在使用”

方法:

void CreateStoredProcedures(string type) { string spLocation = File.ReadAllText("CreateStoredProcedures.sql"); var conn = new SqlConnection(connectionString + ";database=" + type + DateTime.Now.ToString("yyyyMMdd")); try { Server server = new Server(new ServerConnection(conn)); server.ConnectionContext.ExecuteNonQuery(spLocation); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } bool DetachBackup(string type) { var conn = new SqlConnection(connectionString); SqlCommand command = new SqlCommand("", conn); command.CommandText = @"sys.sp_detach_db '" + type + DateTime.Now.ToString("yyyyMMdd") + "'"; try { conn.Open(); command.ExecuteNonQuery(); } catch (Exception ex) { MessageBox.Show(ex.ToString()); return false; } finally { if ((conn.State == ConnectionState.Open)) { conn.Close(); } } return true; } 

点击事件:

 private void btnFullBackup_Click(object sender, EventArgs e) { lblStatus.Text = "Starting full backup..."; Execute("FULL"); progressBar.Value = 20; lblStatus.Text = "Copying tables..."; progressBar.Value = 60; CopyTables("FULL"); progressBar.Value = 70; lblStatus.Text = "Creating stored procedures..."; CreateStoredProcedures("FULL"); progressBar.Value = 80; CheckDBSize(newBackupLocation, "FULL"); progressBar.Value = 100; MessageBox.Show("Backup was created successfully", "", MessageBoxButtons.OK, MessageBoxIcon.Information); lblStatus.Text = "Done"; progressBar.Value = 0; if (DetachBackup("FULL") == false) { DetachBackup("FULL"); } } 

您不应该将其视为数据库“忙”,但错误消息使用良好的verbage: 正在使用中 。 要查明数据库当前是否正在使用,最准确的方法是通过查询sys.dm_tran_lockssys.dm_tran_locks特定数据库中是否存在任何锁定。 这是一个帮助函数,无论数据库是否正在使用,都返回bool

  bool IsDatabaseInUse(string databaseName) { using (SqlConnection sqlConnection = new SqlConnection("... your connection string ...")) using (SqlCommand sqlCmd = new SqlCommand()) { sqlCmd.Connection = sqlConnection; sqlCmd.CommandText = @"select count(*) from sys.dm_tran_locks where resource_database_id = db_id(@database_name);"; sqlCmd.Parameters.Add(new SqlParameter("@database_name", SqlDbType.NVarChar, 128) { Value = databaseName }); sqlConnection.Open(); int sessionCount = Convert.ToInt32(sqlCmd.ExecuteScalar()); if (sessionCount > 0) return true; else return false; } } 

注意:确保连接字符串中的初始目录不是您尝试“未使用”的数据库,因为它会将您当前的会话放在数据库的上下文中,而不允许该操作完成

它有可能挂在它自己的连接上。 sp_detach_db的MSDN https://msdn.microsoft.com/en-CA/library/ms188031.aspx在获取独占访问权限部分下面有以下建议:

 USE master; ALTER DATABASE [DBName] SET SINGLE_USER; 

你的DetachBackup方法将连接到master,运行ALTER和sp_detach_db过程。

您没有在CreateStoredProcedures方法中关闭连接。 像我在这里展示的那样使用语句,它应该解决问题。 ( 简要使用Microsoft的声明解释。 )

尝试使用此代码的方法:

  void CreateStoredProcedures(string type) { string spLocation = File.ReadAllText("CreateStoredProcedures.sql"); using (var conn = new SqlConnection(connectionString + ";database=" + type + DateTime.Now.ToString("yyyyMMdd"))) { try { Server server = new Server(new ServerConnection(conn)); server.ConnectionContext.ExecuteNonQuery(spLocation); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } // End of using, connection will always close when you reach this point. } bool DetachBackup(string type) { using (var conn = new SqlConnection(connectionString)) { SqlCommand command = new SqlCommand(@"sys.sp_detach_db '" + type + DateTime.Now.ToString("yyyyMMdd") + "'", conn); try { conn.Open(); command.ExecuteNonQuery(); } catch (Exception ex) { MessageBox.Show(ex.ToString()); return false; } } // End of using, connection will always close when you reach this point. return true; }