1

当尝试将 SQLite 与 System.Transactions TransactionScope 与身份生成器作为增量一起使用时,我注意到当 NHibernate 试图检索下一个身份编号时,我遇到了一个异常(下面连同代码一起给出)。

这似乎是因为新的 SQLite 连接正在执行当前事务的自动登记。据我所知,SQLite 只支持单写事务,但应该支持多读,所以我很惊讶我得到一个读操作的数据库锁定异常。有没有人以这种方式使用带有事务范围的 SQLite。

如果我使用 NHibernate Transaction 而不是 TransactionScope,则相同的代码可以正常工作

代码块:

           using (var scope = new TransactionScope()) 
            { 
                var userRepository = 
container.GetInstance<IUserRepository>(); 
                var user = new User(); 
                userRepository.SaveOrUpdate(user); 
                scope.Complete(); 
            } 

例外:

19:34:19,126 ERROR [   7] IncrementGenerator [(null)]- could not get 
increment value 
System.Data.SQLite.SQLiteException: The database file is locked 
database is locked 
   at System.Data.SQLite.SQLite3.Step(SQLiteStatement stmt) 
   at System.Data.SQLite.SQLiteCommand.ExecuteNonQuery() 
   at System.Data.SQLite.SQLiteTransaction..ctor(SQLiteConnection 
connection, Boolean deferredLock) 
   at System.Data.SQLite.SQLiteConnection.BeginTransaction(Boolean 
deferredLock) 
   at System.Data.SQLite.SQLiteConnection.BeginTransaction() 
   at System.Data.SQLite.SQLiteEnlistment..ctor(SQLiteConnection cnn, 
Transaction scope) 
   at 
System.Data.SQLite.SQLiteConnection.EnlistTransaction(Transaction 
transaction) 
   at System.Data.SQLite.SQLiteConnection.Open() 
   at NHibernate.Connection.DriverConnectionProvider.GetConnection() 
   at NHibernate.Id.IncrementGenerator.GetNext(ISessionImplementor 
session) 
19:34:20,063 ERROR [   7] ADOExceptionReporter [(null)]- The database 
file is locked 
database is locked
4

1 回答 1

3

这里有两件事在起作用。

正如您所提到的,System.Data.SQLite将在分布式事务中自动登记。这是默认开启的,可以通过添加来关闭它Enlist=no

第二个是System.Data.SQLite默认情况下创建具有自动写锁的事务。这是基于这样的假设:如果一个事务启动,就会完成写入。这可以通过使用 启动事务来覆盖Serializable.ReadCommitted

也可以使用DefaultIsolationLevel键在连接字符串中指定默认值。有效值是ReadCommittedSerializable仅。SQLite 不支持其他隔离级别。 ReadCommitted延迟写锁而Serializable立即获得写锁。

未指定将使用连接字符串中指定的默认隔离级别。如果连接字符串中没有指定隔离级别,则使用 Serializable。可序列化事务是默认设置。在这种模式下,引擎会立即锁定数据库,并且没有其他线程可以开始事务。其他线程可以从数据库中读取,但不能写入。

使用 ReadCommitted 隔离级别,锁会根据需要延迟和提升。多个线程可以在 ReadCommitted 模式下启动事务,但如果一个线程尝试提交事务,而另一个线程具有 ReadCommitted 锁,则可能会超时或导致两个线程死锁,直到两个线程的 CommandTimeout 都达到。

于 2010-03-22T17:31:21.927 回答