2013-07-11 19 views
31

Otrzymuję Baza danych jest zablokowana wyjątek od SQLite tylko w przypadku niektórych zapytań.Baza danych SQLite Zablokowany wyjątek

Poniżej znajduje się mój kod: Po uruchomieniu dowolnego polecenia select działa poprawnie.
Kiedy wykonuję każde polecenie zapisu na tabeli Jobs, to również działa poprawnie.

Działa to dobrze:

ExecuteNonQuery("DELETE FROM Jobs WHERE id=1"); 

Ale tak samo jakbym wykonywania kwerend dla Employees tabeli to rzuca wyjątek, który baza danych jest zablokowana.
ta rzuca wyjątek:

ExecuteNonQuery("DELETE FROM Employees WHERE id=1"); 

Poniżej są moje funkcje:

public bool OpenConnection() 
{ 
    if (Con == null) 
    { 
     Con = new SQLiteConnection(ConnectionString); 
    } 
    if (Con.State == ConnectionState.Closed) 
    { 
     Con.Open(); 
     //Cmd = new SQLiteCommand("PRAGMA FOREIGN_KEYS=ON", Con); 
     //Cmd.ExecuteNonQuery(); 
     //Cmd.Dispose(); 
     //Cmd=null; 
     return true; 
    } 
    if (IsConnectionBusy()) 
    { 
     Msg.Log(new Exception("Connection busy")); 
    } 
    return false; 
} 

public Boolean CloseConnection() 
{ 
    if (Con != null && Con.State == ConnectionState.Open) 
    { 
     if (Cmd != null) Cmd.Dispose(); 
     Cmd = null; 
     Con.Close(); 
     return true; 
    } 

    return false; 
} 

public Boolean ExecuteNonQuery(string sql) 
{ 
    if (sql == null) return false; 
    try 
    { 
     if (!OpenConnection()) 
      return false; 
     else 
     { 
      //Tx = Con.BeginTransaction(IsolationLevel.ReadCommitted); 
      Cmd = new SQLiteCommand(sql, Con); 
      Cmd.ExecuteNonQuery(); 
      //Tx.Commit(); 
      return true; 
     } 
    } 
    catch (Exception exception) 
    { 
     //Tx.Rollback(); 
     Msg.Log(exception); 
     return false; 
    } 
    finally 
    { 
     CloseConnection(); 
    } 
} 

To jest wyjątek: Na linii 103: Cmd.ExecuteNonQuery();

Wyjątek Znaleziono: Typ: System. Data.SQLite.SQLiteException Wiadomość: baza danych jest zablokowana Baza danych jest zablokowana Źródło: System.Data.SQLite

StackTrace: co System.Data.SQLite.SQLite3.Step (SQLiteStatement stmt) na System.Data.SQLite.SQLiteDataReader.NextResult() na System.Data .SQLite.SQLiteDataReader..ctor (cmd SQLiteCommand, CommandBehavior zachowują) na System.Data.SQLite.SQLiteCommand.ExecuteReader (zachowanie CommandBehavior) na System.Data.SQLite.SQLiteCommand.ExecuteNonQuery() na TimeSheet6.DbOp.ExecuteNonQuery (String sql) w d: \ Projects \ C# Applications \ Completed Projects \ TimeSheet6 \ TimeSheet6 \ DbOp.cs: line 103

+0

Upewnij się, że zamkniesz połączenie, które wykonuje Twoje żądanie. –

+0

Tak, również zamknąłem wszystkie połączenia i rozłożyłem obiekty poleceń. – coding

+0

Zrobiłem dużo debugowania za tym. To nie wydaje się być problemem otwartego połączenia. – coding

Odpowiedz

74

Gdzieś po drodze połączenia wychodzi pozostać otwarta. Pozbądź OpenConnection i CloseConnection i zmienić ExecuteNonQuery do tego:

using (SQLiteConnection c = new SQLiteConnection(ConnectionString)) 
{ 
    c.Open(); 
    using (SQLiteCommand cmd = new SQLiteCommand(sql, c)) 
    { 
     cmd.ExecuteNonQuery(); 
    } 
} 

Ponadto, zmienić sposób czytać dane do tego:

using (SQLiteConnection c = new SQLiteConnection(ConnectionString)) 
{ 
    c.Open(); 
    using (SQLiteCommand cmd = new SQLiteCommand(sql, c)) 
    { 
     using (SQLiteDataReader rdr = cmd.ExecuteReader()) 
     { 
      ... 
     } 
    } 
} 

nie próbuj, zarządzać połączenie łączenie na twoja własna jak ty jesteś tutaj. Po pierwsze, jest znacznie bardziej skomplikowany niż to, co zakodowałeś, ale po drugie, jest on obsługiwany już wewnątrz obiektu SQLiteConnection. Na koniec, jeśli nie używasz using, nie musisz prawidłowo pozbywać się tych obiektów, a na koniec będziesz mieć problemy takie jak to, co teraz widzisz.

+0

Dzięki .. Spróbuję tego w ten sposób. – coding

+0

Czy istnieje jakakolwiek inna przyczyna takiego wyjątku, z wyjątkiem niewłaściwego wyrzucania obiektów. – coding

+0

@ kodowanie, tak. Zawsze istnieją inne sposoby blokowania plików, ale podstawowym podejrzanym jest niewłaściwe obchodzenie się z obiektami połączenia (takimi jak oryginalny kod). –

13

Można użyć „używając” oświadczenie jak poniżej, który zadba polecenia Połączenie & umieszczonych poprawnie nawet w wyjątku

private static void ExecuteNonQuery(string queryString) 
{ 
    using (var connection = new SQLiteConnection(
       ConnectionString)) 
    { 
     using (var command = new SQLiteCommand(queryString, connection)) 
     { 
      command.Connection.Open(); 
      command.ExecuteNonQuery(); 
     } 
    } 
} 
+0

Dzięki .. Wykorzystam to podejście. – coding

+0

Dzięki .. za twoją radę. Zaimplementowałem go i teraz nie są zgłaszane żadne wyjątki. – coding

0
I was also getting the same error here 

if (new basics.HindiMessageBox(HMsg, HTitle).ShowDialog()==true) 
{ 
    SQLiteConnection m_dbConnection = new SQLiteConnection(MainWindow.con); 
    m_dbConnection.Open(); 
    sql = "DELETE FROM `users` WHERE `id`=" + SelectedUser.Id; 
    command = new SQLiteCommand(sql, m_dbConnection); 
    command.ExecuteNonQuery(); 
    m_dbConnection.Close(); 
    LoadUserDG(); 
} 

ale kiedy tylko zmienił SQLiteConnection declearation miejsce

public partial class User : Window 
    { 

     SQLiteCommand command; 
     string sql; 
     AddUser AddUserObj; 
     List<basics.users> usersList; 
     basics.users SelectedUser; 
     SQLiteConnection m_dbConnection; 
..... 
..... 
..... 
..... 
     private void DeleteBtn_Click(object sender, RoutedEventArgs e) 
     { 
      .... 
      .... 
      .... 
      if (new basics.HindiMessageBox(HMsg, HTitle).ShowDialog()==true) 
      { 
       m_dbConnection = new SQLiteConnection(MainWindow.con); 
       m_dbConnection.Open(); 
       sql = "DELETE FROM `users` WHERE `id`=" + SelectedUser.Id; 
       command = new SQLiteCommand(sql, m_dbConnection); 
       command.ExecuteNonQuery(); 
       m_dbConnection.Close(); 
       LoadUserDG(); 
      } 
     } 

wszystko jest już w porządku. mam nadzieję, że to może działać również dla Ciebie. jeśli ktoś może powiedzieć, jak to się stało, proszę powiedzieć, że chciałbym wiedzieć, aby poprawić moją wiedzę.

+0

Powinieneś użyć "Używanie", gdzie tylko możliwe! Tak jak pokazali ci Mike Perrenoud i Damith. "Używanie" zostało wymyślone ze względów kontrolnych/bezpieczeństwa, powinieneś naprawdę go użyć. – tmighty

0

Przed zapisaniem danych w bazie danych należy zamknąć urządzenie DataReader. Użyj:

dr.Close(); 

po zakończeniu korzystania z DataReader.

Powiązane problemy