2013-09-15 4 views
1

У меня есть база данных SQL Server и старая резервная копия этой базы данных. Иногда мне приходится проверять некоторые данные в резервной копии с помощью приложения C# WinForms. Я восстанавливаю файл резервной копии, используя этот пост: How to restore to a different database in sql server?.Ошибка базы данных сервера 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().

P.S. Я использую функцию database.ReadDataBaseIstoric() также для чтения данных из текущей базы данных (а не восстановленной резервной копии), там она отлично работает, без каких-либо ошибок или исключений.

+0

Помимо моего решения, я вижу, что вы закрываете соединение, прежде чем запускаете его, поэтому может возникнуть проблема. –

ответ

2

Попробуйте изменить функцию:

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); 
     } 
    } 
} 

использования закроется и распоряжаться объектами.

+0

Было бы неплохо проверить наличие conn! = Null в блоке catch и вызвать conn.dispose(). Чтобы быть действительно правильным, то же самое для cmd и reader. Или поместите внутренние блоки catch вокруг используемых операторов и вызовите бросок во внутренних. –

+0

@ TonyHopkinson Итак, вы говорите, что я должен был покинуть окончательную часть? –

+0

Использование не в порядке, просто нужно убедиться, что если исключение получило, все неявные или явные выражения окончательно выполняются. Похоже, они могли бы в этом случае после более пристального взгляда. –

2

У вас здесь три проблемы. Во-первых, вы не распоряжаетесь, как было предложено @jyparask.

Другое по умолчанию используется пул соединений. Это означает, что даже если вы закроете соединение, он останется в пуле в течение времени по умолчанию (думаю, 2 минуты). Поэтому, если бы я делал это, я бы добавил pooling = false в эту строку соединения. Из-за этого я могу против всех рекомендаций, например, установить соединение, а затем передать его и утилизировать во время операции сбрасывания.

Последнее, но не менее важное: вы подключаетесь к базе данных, которую вы пытаетесь удалить, не так ли? Лучше всего было бы создать новое соединение с базой данных Master, чтобы удалить тот, который вы хотите.

+1

Я подключаюсь к основной базе данных, когда пытаюсь удалить базу данных. См. Событие private void Arhiva_FormClosing (объект отправителя, FormClosingEventArgs e). Остальные 2 проблемы существуют. – Jaws

+0

Так вы, мои извинения. –

Смежные вопросы