2013-03-13 3 views
6

Wie ich von SQLite FAQ lesen kann, unterstützt es mehrere Prozesse lesen (SELECT) und nur einen Prozess schreiben (INSERT, UPDATE, DELETE) Datenbank jederzeit in Zeit:Mehrfacher Zugriff auf eine einzelne SQLite-Datenbankdatei über System.Data.SQLite und C#

SQLite verwendet Reader/Writer-Sperren, um den Zugriff auf die Datenbank zu steuern. Wenn ein Prozess schreiben möchte, muss er die gesamte Datenbankdatei für die Dauer der Aktualisierung sperren. Aber das dauert normalerweise nur ein paar Millisekunden. Andere Prozesse warten nur auf den Autor zu beenden dann weiter über ihr Geschäft

I System.Data.SQLite Adapter via C# bin mit.

Könnte jemand mich plz explodieren, wie genau dieser Prozess läuft?

Wird dieser Prozess funktioniert automatisch und Schreiben SQLiteCommand wird einfach warten, wenn es eine andere Schrift ist SQLiteCommand bereits die gleiche Datenbank ausgeführt wird über?

Oder vielleicht wird es eine Ausnahme werfen? Was für eine Art davon?

Sorry, aber ich fand keine Informationen zu dieser Mechanik :)

Danke.

UPDATE:

ich Post gefunden habe sagen, dass exception will be raised mit einem bestimmten Fehlercode

Ist diese Aussage richtig?

+0

Haben Sie es versucht? – Default

+0

Noch nicht :) Ich lese lieber Tutorials vor dem Codieren - um optimierte und korrekte Lösungen zu bekommen ... – bairog

+1

Wenn Sie "optimierte und korrekte Lösungen" bevorzugen, verwenden Sie SQLite nicht für etwas, für das es nicht optimiert wurde; es ist eine großartige Datenbank, aber eine großartige Multi-User-Datenbank ist es nicht. – Tim

Antwort

10

Ich habe es von mir untersucht:

Ich habe eine Probe SQLite-Datenbank c:\123.db mit einer Tabelle Categories enthält zwei Felder: ID (unique) und Name (nvarchar).

Ich schrieb dann einen Code Multi-Thread mehrere Schreibzugriff auf die Datenbank emulieren (vergessen Sie nicht, einen System.Data.SQLite Bezug zu einem Projekt hinzuzufügen, wenn Sie diesen Code verwenden):

using System; 
using System.Data.SQLite; 
using System.Threading.Tasks; 

namespace SQLiteTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var tasks = new Task[100]; 

      for (int i = 0; i < 100; i++) 
      { 
       tasks[i] = new Task(new Program().WriteToDB); 
       tasks[i].Start(); 
      } 

      foreach (var task in tasks) 
       task.Wait(); 
     } 

     public void WriteToDB() 
     { 
      try 
      { 
       using (SQLiteConnection myconnection = new SQLiteConnection(@"Data Source=c:\123.db")) 
       { 
        myconnection.Open(); 
        using (SQLiteTransaction mytransaction = myconnection.BeginTransaction()) 
        { 
         using (SQLiteCommand mycommand = new SQLiteCommand(myconnection)) 
         { 
          Guid id = Guid.NewGuid(); 

          mycommand.CommandText = "INSERT INTO Categories(ID, Name) VALUES ('" + id.ToString() + "', '111')"; 
          mycommand.ExecuteNonQuery(); 

          mycommand.CommandText = "UPDATE Categories SET Name='222' WHERE ID='" + id.ToString() + "'"; 
          mycommand.ExecuteNonQuery(); 

          mycommand.CommandText = "DELETE FROM Categories WHERE ID='" + id.ToString() + "'"; 
          mycommand.ExecuteNonQuery(); 
         } 
         mytransaction.Commit(); 
        } 
       } 
      } 
      catch (SQLiteException ex) 
      { 
       if (ex.ReturnCode == SQLiteErrorCode.Busy) 
        Console.WriteLine("Database is locked by another process!"); 
      } 
     } 
    } 
} 

Das Ergebnis auf Mein Core2Duo E7500 ist, dass Exception nie ausgelöst wird!

Sieht so aus, als wäre SQLite für meine Bedürfnisse optimiert (das Sperren/Entsperren ist sehr schnell und dauert normalerweise nur ein paar Millisekunden, wie uns SQLite FAQ sagt) - Großartig!

Beachten Sie, dass es nicht erforderlich ist, eine ganze Zahl ErrorCode für eine SQLiteException abzurufen - Sie können stattdessen ein spezielles enum ReturnCode Feld verwenden. Alle Codes sind beschrieben here.

Hoffe, diese Informationen werden jemandem helfen.

+1

Ihr Code beweist, dass mehrere Threads innerhalb eines * einzigen * Prozesses nahtlos auf die SQLite-Datenbank zugreifen können. Konnten Sie testen, ob mehrere verschiedene Prozesse auf dieselbe Datenbank zugreifen können? – pmont

+0

Nun, zuerst kommt mir in den Sinn, diesen Code in ** Test1.exe ** zu kompilieren, als ** Process.Start ("Test1.exe") ** in der ersten Zeile von ** Main ** hinzuzufügen und neu zu kompilieren es zu ** Test2.exe **. Scheint zu arbeiten, aber ich habe es nie getestet ... – bairog

+3

Gute Idee! Ich habe gerade mit diesem Ansatz getestet und es funktioniert. Multiprozesszugriff funktioniert problemlos mit SQLite. – pmont

Verwandte Themen