2011-07-19 39 views
14

System.Data.SQLite ile ilginç bir sorun yaşıyorum ve birden çok işlem kullanıyor.System.Data.SQLite Çoklu İşlemleri Desteklemiyor

using (IDbConnection connection1 = new SQLiteConnection("connectionstring"), connection2 = new SQLiteConnection("connectionstring")) 
{ 
    connection1.Open(); 
    connection2.Open(); 

    IDbTransaction transaction1 = connection1.BeginTransaction(); 
    IDbTransaction transaction2 = connection2.BeginTransaction(); // Fails! 

    using(IDbCommand command = new SQLiteCommand()) 
    { 
     command.Text = "CREATE TABLE artist(artistid int, artistname text);"; 
     command.CommandType = CommandType.Text; 
     command.Connection = connection1; 
     command.ExecuteNonQuery(); 
    } 

    using (IDbCommand command = new SQLiteCommand()) 
    { 
     command.Text = "CREATE TABLE track(trackid int, trackname text);"; 
     command.CommandType = CommandType.Text; 
     command.Connection = connection2;      
     command.ExecuteNonQuery(); 
    } 

    transaction1.Commit(); 
    transaction2.Commit(); 

} 

Ben System.Data.SQLite iç içe ve uzantı sıralı işlemleri desteklemelidir görünüyor okuduğum kadarıyla: Temelde ben başarısız aşağıdaki kodu var.

System.Data.SQLite.SQLiteException: The database file is locked 

System.Data.SQLite.SQLite3.Step(SQLiteStatement stmt) 
System.Data.SQLite.SQLiteDataReader.NextResult() 
System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave) 
System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior) 
System.Data.SQLite.SQLiteCommand.ExecuteNonQuery() 
System.Data.SQLite.SQLiteTransaction..ctor(SQLiteConnection connection, Boolean deferredLock) 
System.Data.SQLite.SQLiteConnection.BeginDbTransaction(IsolationLevel isolationLevel) 
System.Data.Common.DbConnection.System.Data.IDbConnection.BeginTransaction() 

kimse konudur ya bu nasıl aşmanın biliyor mu

: Kod şu istisna ile (ikinci işlem bildirildi) on line 7 başarısız? Eşzamanlı işlemlerin herhangi bir veritabanı sistemi için gerekli olduğunu hissediyorum, bu yüzden bunu yapmanın bir yolu olmalı.

Teşekkürler!

+1

Kodunuza çok yakından bakın ... İlk kullanım deyiminde yeni 'command1' size ama 'command' – JonH

+0

Typo' ya bakın, düzeltin –

cevap

14

OP, 2 bağlantıda işlemleri başlatıyor, sorunların başladığı yer burası, birden fazla işlemde değil.

SQLiteConnection conn = new SQLiteConnection("data source=:memory:"); 
conn.Open(); 

var command = conn.CreateCommand(); 
command.CommandText = "create table a (b integer primary key autoincrement, c text)"; 
command.ExecuteNonQuery(); 

var tran1 = conn.BeginTransaction(); 
var tran2 = conn.BeginTransaction(); 

var command1 = conn.CreateCommand(); 
var command2 = conn.CreateCommand(); 

command1.Transaction = tran1; 
command2.Transaction = tran2; 

command1.CommandText = "insert into a VALUES (NULL, 'bla1')"; 
command2.CommandText = "insert into a VALUES (NULL, 'bla2')"; 

command1.ExecuteNonQuery(); 
command2.ExecuteNonQuery(); 

tran1.Commit(); 
tran2.Commit(); 

command.CommandText = "select count(*) from a"; 
Console.WriteLine(command.ExecuteScalar()); 
-1

Değeri için, tek bir bağlantı için birden fazla işlemin desteklenmemesi veri sağlayıcılar için yaygın görünmüyor (ODP.NET, muhtemelen başkalarını biliyorum).

Etrafında çalışmanın bir yolu, her IDbTransaction için ayrı bir IDbConnection olmalıdır.

- EDIT ---

Doh! Sadece fark ettim ki, 'un çoklu bağlantıları var. Afedersiniz.

+0

sqlite birden fazla işlemi destekler. –

-1

SQLite birden çok işlemi desteklemez - işlemin tamamında veritabanının tamamını kilitler (bkz. Www.sqlite.org).

DÜZENLEME: Birden çok işlem desteklenir, ancak birden çok işlemde DDL kullanıldığında desteklenmez.

+0

Bu doğru değil. –

+0

Örneğin Oracle'da ve SQLite'de çoklu işlem desteğini karşılaştırdığınızda, SQLite'nin bunun için sadece "simüle" ettiğini göreceksiniz ... örnekle orijinal soru arasında bir fark var, DML kullanıyorsunuz ve DDL'yi kullanıyor Her iki işlem ... Cevabımı buna göre değiştirdim. – Yahia

3

SQLite, tarayıcıdaki yer imleri veya fotoğraf katalog programındaki fotoğraflar gibi hafif bir veritabanı olarak tasarlanmıştır. SQLite, çok sayıda okuyucu veya tek bir okuyucu/yazıcı iş parçacığı ile senaryolar için optimize edilmiş çok ayrıntılı bir kilitleme sistemine sahiptir. Eşzamanlı yazımlarla - ile performans problemleri olduğu bilinen bir çok uyumlu yazarlar ile uygulamalarda kullanılmak üzere tasarlanmamıştır. Eşzamanlı yazmalar için do yapabilirsiniz, ancak iyi ölçeklenmeyecektir. Bunun yerine o zaman bu olacak eser başarıyla birden SELECT veya çoklu INSERT ifadeleri yaptıysam (sixfeetsix cevabı gösterileri gibi) - Eğer eşzamanlı şema değişiklikleri yapmak için çalışıyorsunuz çünkü sorundur Bu durumda

.

Başvurunuz pek çok okuyucuyu ve pek yazarları sonra SQLite iyi o zaman tam teşekküllü veritabanı sunucusu daha uygun olduğunu görebilirsiniz birçok eşzamanlı okuyucular ve yazarlar ile bir uygulama var ancak eğer ince olabilir varsa.

Daha fazla ayrıntı için bkz. File Locking And Concurrency In SQLite Version 3.

+0

bunun gibi üçüncü bir cevabı kaldı ... sqlite _does_ çoklu işlemleri destekliyor. –

+0

@sixfeetsix Son düzenlemem bazı şeyleri biraz daha netleştiriyor mu? – Justin

+1

Evet, şimdi biraz daha iyi anladığım kadarıyla bir geri çekiyorum, ama benim perspektifim sadece kendimi OP'nin ayakkabılarına koyduğumda, o topluluğun tercih edilmesini istediğimi düşünüyorum. Sorunumu biraz daha doğrudan ele alalım, yani çoklu yazma bağlantılarının sorun olduğunu söyleyemem ve daha sonra sadece bir işleme yapmanın neden daha iyi olabileceğine dair bir konuşma olarak. –

1

deneyin kullanmak:

((SQLiteConnection)connection).BeginTransaction(true)- 

bool parametresi deferredLock anlatır. Ancak, ExecuteNonScalar'ın yalnızca ilk işlemin yapılmasından sonra çağrılması gerektiğini unutmayın.

İlgili konular