SQL 服务器删除数据库失败
本文关键字:失败 数据库 删除 服务器 SQL | 更新日期: 2023-09-27 18:31:18
我有一个SQL Server数据库和该数据库的旧备份。有时我必须使用 C# WinForms 应用程序验证备份副本中的某些数据。我使用这篇文章还原备份文件: 如何还原到 sql 服务器中的其他数据库?.
我的恢复功能如下所示:
SqlConnection myConn = new SqlConnection("Server=.''sqlexpress;Database=master;Trusted_Connection=True;");
try
{
if (!Databases.CheckDatabaseExists(myConn, fileName))
{
myConn.Open();
SqlCommand cmd = new SqlCommand("RESTORE FILELISTONLY FROM DISK='" + fileName + ".bak'", myConn);
SqlDataReader reader = cmd.ExecuteReader();
cmd.CommandText = "restore database " + Path.GetFileName(fileName) + " from disk = '" + fileName + ".bak' with move'";
int i = 0;
while (reader.Read())
{
if (i == 0)
{
cmd.CommandText += reader[0].ToString() + "' to '" + filePath + "''" + Path.GetFileName(fileName) + ".mdf', move ";
i++;
}
else
{
cmd.CommandText += "'" + reader[0].ToString() + "' to '" + filePath + "''" + Path.GetFileName(fileName) + ".mdf.ldf'";
}
}
reader.Close();
cmd.ExecuteNonQuery();
myConn.Close();
database.ReadDataBaseIstoric(dataGridView1, Path.GetFileName(fileName));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if (myConn.State == ConnectionState.Open) { myConn.Close(); }
}
和
database.ReadDataBaseIstoric(dataGridview1,Path.GetFileName(filename));
从还原的数据库中读取数据,如下所示:
public void ReadDataBaseIstoric(DataGridView dataGridView1, string dataBaseName)
{
dataGridView1.Rows.Clear();
SqlConnection conn = new SqlConnection("Server=.''sqlexpress;Trusted_Connection=true;database=" + dataBaseName + ";");
SqlDataReader reader = null;
try
{
conn.Open();
SqlCommand cmd = new SqlCommand("select * from istoric", conn);
conn.Close();
reader = cmd.ExecuteReader();
while (reader.Read())
{
string[] str = new string[5] { reader[0].ToString(), reader[1].ToString(), reader[2].ToString(), reader[3].ToString(), reader[4].ToString() };
dataGridView1.Rows.Add(str);
}
reader.Close();
conn.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if (reader != null && !reader.IsClosed) { reader.Close(); }
if (conn.State == ConnectionState.Open) { conn.Close(); }
}
}
目前一切正常。问题是,当我尝试删除还原的数据库时,它会返回 en 错误,指出无法删除该数据库,因为它仍在使用中。这就是我想删除数据库的方式:
private void Arhiva_FormClosing(object sender, FormClosingEventArgs e)
{
bool closed = false;
if (!closing) { e.Cancel = true; closing = false; closed = true; }
SqlConnection myConn = new SqlConnection("Server=.''sqlexpress;Database=master;Trusted_Connection=True;");
try
{
if (Databases.CheckDatabaseExists(myConn, Path.GetFileName(fileName)))
{
myConn.Open();
SqlCommand cmd = new SqlCommand("DROP DATABASE "+Path.GetFileName(fileName), myConn);
cmd.ExecuteNonQuery();
myConn.Close();
label1.Visible = false;
}
else
{
MessageBox.Show("Exista deja o baza de date cu numele '" + fileName + "'.", "VivaFEED", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if (myConn.State == ConnectionState.Open) { myConn.Close(); }
}
if (closed) { this.Close(); }
}
我尝试在从中读取数据之前删除还原的数据库,并且效果很好,所以我认为问题应该出在database.ReadDataBaseIstoric()
上。
附言我也使用 database.ReadDataBaseIstoric()
函数从当前数据库(不是还原的备份)中读取数据,它在那里工作得很好,没有任何错误或异常。
尝试将函数更改为:
public void ReadDataBaseIstoric(DataGridView dataGridView1, string dataBaseName)
{
dataGridView1.Rows.Clear();
using(SqlConnection conn = new SqlConnection("Server=.''sqlexpress;Trusted_Connection=true;database=" + dataBaseName + ";"))
using(SqlCommand cmd = new SqlCommand("select * from istoric", conn))
{
SqlDataReader reader = null;
try
{
conn.Open();
using(SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
string[] str = new string[5] { reader[0].ToString(), reader[1].ToString(), reader[2].ToString(), reader[3].ToString(), reader[4].ToString() };
dataGridView1.Rows.Add(str);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
使用将关闭并释放对象。
你这里有三个问题。首先,您没有按照@jyparask的建议进行处置。
另一个是默认情况下您正在使用连接池。这意味着即使您关闭连接,它在池中也会在默认时间内保持活动状态(我认为为 2 分钟)。因此,如果我这样做,我也会向该连接字符串添加 pooling = false。因此,我可能会反对所有建议,实例化一个连接,然后在删除操作期间传递并处理它
最后但并非最不重要的一点是,您正在连接到您尝试删除的数据库,不是吗?最好的办法是创建一个与 Master 数据库的新连接,以便删除所需的连接。