带有TransactionScope和增量标识生成器的SQLite

时间:2010-03-22 16:11:33

标签: nhibernate sqlite transactionscope

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

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

如果我使用NHibernate事务而不是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

1 个答案:

答案 0 :(得分:3)

这里有两件事情。

正如您所提到的,System.Data.SQLite将在分布式事务中自动登记。默认情况下处于启用状态,可以通过添加Enlist=no来关闭它。

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

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

  

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

     

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