当尝试将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
答案 0 :(得分:3)
这里有两件事情。
正如您所提到的,System.Data.SQLite
将在分布式事务中自动登记。默认情况下处于启用状态,可以通过添加Enlist=no
来关闭它。
第二个是System.Data.SQLite
默认情况下使用自动写锁定创建事务。这是基于如果启动事务,将完成写入的假设来完成的。这可以通过使用Serializable.ReadCommitted
启动交易来覆盖。
也可以使用DefaultIsolationLevel
键在连接字符串中指定默认值。有效值仅为ReadCommitted
和Serializable
。 SQLite不支持其他隔离级别。 ReadCommitted
延迟写锁定,而Serializable
立即获得写锁定。
未指定将使用连接字符串中指定的默认隔离级别。如果在连接字符串中未指定隔离级别,则使用Serializable。可序列化事务是默认值。在此模式下,引擎会立即锁定数据库,并且没有其他线程可以开始事务。其他线程可以从数据库中读取,但不能写入。
使用ReadCommitted隔离级别,锁定会根据需要延迟和提升。多线程可以在ReadCommitted模式下启动事务,但是如果一个线程尝试提交事务而另一个线程具有ReadCommitted锁,则它可能会超时或导致两个线程出现死锁,直到达到两个线程的CommandTimeout。 / p>