C#无法分离数据库

时间:2015-10-06 10:09:28

标签: c# sql-server ado.net

我有一个类,它创建一个数据库,将mdf文件保存在指定位置。然后它从现有数据库中复制表。然后从sql文件创建存储过程。然后,在完成该过程后,将从开始创建的数据库分离。我的问题是我的detach方法无法抛出异常,说数据库正在使用中。我妥善处理了我的关系。

这与我的previous question一致。

这是我的班级:

Event
    private void btnFullBackup_Click(object sender, EventArgs e)
            {
                progressBar.Value = 0;   
                lblStatus.Text = "Starting full backup...";
                CreateDB("FULL");
                progressBar.Value = 20;      

                lblStatus.Text = "Copying tables...";
                CopyTables("FULL");
                progressBar.Value = 60;

                lblStatus.Text = "Creating stored procedures...";
                CreateStoredProcedures("FULL");
                progressBar.Value = 70;

                progressBar.Value = 80;

                DetachBackup("FULL");

                lblStatus.Text = "Done";
                progressBar.Value = 100;

                MessageBox.Show("Backup was created successfully", "",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);  
            }

使用的方法:

void CreateDB(string type)
        {
            //define and browse location to save mdf
            lblStatus.Text = "Creating pysical database...";
            FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();            
            folderBrowserDialog.ShowDialog();
            lblStatus.Text = "Checking folder permission...";
            string selectedFolder = folderBrowserDialog.SelectedPath + "\\";
            newBackupLocation = selectedFolder;
            //check permission
            if (WriteAccessToFolder(selectedFolder) == false)
            {
                MessageBox.Show("The folder you have chosen does not have write permission", "Monytron",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                folderBrowserDialog.ShowDialog();
                return;
            }

            //create DB
            lblStatus.Text = "Creating database...";
            string connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
            var query = GetDbCreationQuery(selectedFolder, type);
            using (var conn = new SqlConnection(connectionString))
            using (var command = new SqlCommand(query, conn))
            {
                try
                {
                    conn.Open();
                    command.ExecuteNonQuery();
                    folderBrowserDialog.Dispose();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
                finally
                {
                    if ((conn.State == ConnectionState.Open))
                    {
                        conn.Close();
                    }
                }
            }
        }
void CopyTables(string backupDBName)
        {
            string connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
            var query = CopyQuery(backupDBName + DateTime.Now.ToString("yyyyMMdd"));
            using (var conn = new SqlConnection(connectionString))
            using (var command = new SqlCommand(query, conn))
            {
                try
                {
                    conn.Open();
                    command.ExecuteNonQuery();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
                finally
                {
                    if ((conn.State == ConnectionState.Open))
                    {
                        conn.Close();
                    }
                }
            }            
        }

void CreateStoredProcedures(string type)
        {
            string connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
            using (var conn = new SqlConnection(connectionString + ";database=" + type + DateTime.Now.ToString("yyyyMMdd")))
            {
                string spLocation = File.ReadAllText("CreateStoredProcedures.sql");
                Server server = new Server(new ServerConnection(conn));
                try
                {
                    server.ConnectionContext.ExecuteNonQuery(spLocation);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }

bool DetachBackup(string backupDBName)
        {
            string connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
            var builder = new SqlConnectionStringBuilder(connectionString);
            string serverName = builder.DataSource; 
            string dbName = builder.InitialCatalog;
            try
            {
                Server smoServer = new Server(serverName);
                smoServer.DetachDatabase(backupDBName + DateTime.Now.ToString("yyyyMMdd"), false);
                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                return false;
            }
        }

2 个答案:

答案 0 :(得分:1)

大多数情况下,数据库的连接在使用后放在池中。这样您就可以使用相同的连接字符串快速重新连接,但另一方面,我怀疑这个连接池阻止您分离数据库。

你可以这样做:

  • 在关闭连接之前,将use master作为针对数据库的每个查询中的最后一个语句,或
  • 修改连接字符串,使其不使用合并(uid=...; pwd=...; pooling=false;

希望它有所帮助。

答案 1 :(得分:1)

如果要保持连接池,则应首先终止与数据库的连接。您可以在调用detach方法之前使用rollback_immediate子句在单用户访问中设置数据库。

看看这里使用C#: Is there a way to set the DB as Single User Mode in C#?

或者在这里运行T-SQL脚本: https://serverfault.com/questions/76432/how-can-i-detach-a-database-that-is-in-use