2013-03-13 7 views
6

Come posso leggere da SQLite FAQ supporta la lettura di più processi (SELECT) e solo un database di scrittura processo (INSERT, UPDATE, DELETE) in qualsiasi momento in time:Accesso multiplo a un singolo file di database SQLite tramite System.Data.SQLite eC#

SQLite utilizza i blocchi lettore/scrittore per controllare l'accesso al database. Quando qualsiasi processo vuole scrivere, deve bloccare l'intero file di database per la durata del suo aggiornamento. Ma in genere occorrono solo alcuni millisecondi. Altri processi solo aspettare sullo scrittore per finire poi continuare i loro affari

sto usando System.Data.SQLite adattatore via C#.

Qualcuno potrebbe expalin me plz, come esattamente questo processo sta succedendo?

Sarà questo lavoro processo automatico e la scrittura SQLiteCommand semplicemente aspettare se non v'è un altro scritto SQLiteCommand già in esecuzione nello stesso database?

O forse genererà un'eccezione? Che tipo di cosa?

dispiace ma non ho trovato alcuna informazione su questo meccanica :)

grazie.

UPDATE:

ho trovato post dicendo che exception will be raised con uno specifico ErrorCode

È questa affermazione corretta?

+0

Hai provato? – Default

+0

Non ancora :) Preferisco leggere le esercitazioni prima della codifica - per ottenere soluzioni ottimizzate e corrette ... – bairog

+1

Se preferisci "soluzioni ottimizzate e corrette" non utilizzare SQLite per qualcosa per cui non è stato ottimizzato; è un ottimo database, ma non è un grande database multiutente. – Tim

risposta

10

ho indagato da solo:

ho creato un database SQLite campione c:\123.db con una tabella Categories contenente due campi: ID (uniqueidentifier) ​​e Name (nvarchar).

Ho poi scritto un codice multi-thread di emulare l'accesso in scrittura multipla alla banca dati (non dimenticate di aggiungere un riferimento System.Data.SQLite al progetto se si utilizza questo codice):

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

Il risultato su il mio Core2Duo E7500 è che l'eccezione non viene mai sollevata!

Sembra SQLite è ottimizzato abbastanza per le mie esigenze (blocco/sblocco è molto veloce e normalmente richiede solo pochi millisecondi come ci dice SQLite FAQ) - Grande!

Si noti che non è necessario recuperare un numero intero CodiceErrore per un SQLiteException - è possibile utilizzare invece un campo enum speciale ReturnCode. Tutti i codici sono descritti here.

Spero che questa informazione possa aiutare qualcuno.

+1

Il codice dimostra che più thread all'interno di un processo * single * possono accedere senza problemi al database SQLite. Sei riuscito a testare se più processi diversi possono accedere allo stesso database? – pmont

+0

Bene, prima mi viene in mente la compilazione di quel codice in ** Test1.exe **, anziché aggiungere ** Process.Start ("Test1.exe") ** alla prima riga di ** Principale ** e ricompilare a ** Test2.exe **. Sembra funzionare ma non l'ho mai provato ... – bairog

+3

Buona idea! Ho appena testato usando quell'approccio e funziona. L'accesso multi-processo funziona perfettamente con SQLite. – pmont