ORMLite下的SQLite不允许在事务完成后执行任何操作
问题描述:
在通过ServiceStack的OrmLite在SQLite中创建并提交事务后,我无法继续并发出任何查询。ORMLite下的SQLite不允许在事务完成后执行任何操作
例如,下面的测试失败:
[Test, Explicit]
public void Can_query_after_transaction_is_committed()
{
var connection = new OrmLiteConnectionFactory(":memory:", false, SqliteDialect.Provider, true);
using (var db = connection.OpenDbConnection())
{
db.DropAndCreateTable<SimpleObject>();
var trans = db.OpenTransaction();
db.Insert(new SimpleObject{test="test"});
trans.Commit();
Assert.DoesNotThrow(()=> db.Select<SimpleObject>()); //throws
}
}
class SimpleObject{public string test { get; set; }}
我得到的例外是:“交易不与命令的连接相关联的”失败周围OrmLite的that line。但是,我根本不应该参与交易。
当我使用SQL Server与代码提供商像
new OrmLiteConnectionFactory(
@"Data Source=.\SQLEXPRESS;Initial Catalog=TestEmpty;Persist Security Info=True;User ID=db;Password=db;",
false, SqlServerDialect.Provider, true);*/
本次测试工作正常。
我结束了交易不正确吗?这是ServiceStack.OrmLite中的错误吗?
答
原来我在使用的版本中已发现类似问题reported和fixed。经过比较我的测试与the passing one我发现我dindn't处置()我的交易。
最后答案是:该交易必须处置。如果不是,则使用SQLite时代码将失败。
下测试通过:
public void Can_query_after_transaction_is_committed()
{
var connection = new OrmLiteConnectionFactory(":memory:", true, SqliteDialect.Provider, true);
using (var db = connection.OpenDbConnection())
{
db.DropAndCreateTable<SimpleObject>();
using (var trans = db.OpenTransaction())
{
db.Insert(new SimpleObject {test = "test"});
trans.Commit();
}
Assert.DoesNotThrow(()=> db.Select<SimpleObject>());
}
}
答
我的问题是相似的,我搜查这里。试图编写一个单元测试来测试我的服务,我得到了同样的“事务不与命令的连接关联”异常。我的情况不同之处在于,我正在使用的唯一事务(在我测试的服务中)正确地处理了它的连接,所以我不认为这适用。
(我使用的ServiceStack v3.9.71)
我的测试代码(失败)是这样的:
[Test]
public void Test_Service_Delete() {
var DatabaseFactory = new OrmLiteConnectionFactory(":memory:", false, SqliteDialect.Provider, true);
using (var db = DatabaseFactory.OpenDbConnection()) {
var parentId = db.InsertParam(new ParentObject { name = "Bob" }, true);
db.Insert(new ChildObject { ParentId = parentId, name = "Sam" });
var service = Container.Resolve<TestService>();
var response = service.Delete(new DeleteRequestObject(parentId));
Assert.That(db.Select<ParentObject>(parentId), Has.Count.EqualTo(0));
Assert.That(db.Select<ChildObject>("ParentId = {0}", parentId), Has.Count.EqualTo(0));
}
}
我TestService.Delete方法曾在它的事务(因为它会删除对象和任何相关的子对象),但它被包裹在一个使用块,像这样:
using (var db = DatabaseFactory.OpenDbConnection()) {
using (var transaction = db.BeginTransaction(IsolationLevel.ReadCommitted)) {
// do stuff here
}
}
不过,除了W“交易不与命令的连接相关联”在调用service.Delete之后在第一行中抛出。
我首先要解决它(没有工作)的尝试是这样的:
[Test]
public void Test_Service_Delete() {
var DatabaseFactory = new OrmLiteConnectionFactory(":memory:", false, SqliteDialect.Provider, true);
int parentId;
using (var db = DatabaseFactory.OpenDbConnection()) {
parentId = db.InsertParam(new ParentObject { name = "Bob" }, true);
db.Insert(new ChildObject { ParentId = parentId, name = "Sam" });
}
var service = Container.Resolve<TestService>();
var response = service.Delete(new DeleteRequestObject(parentId));
using (var db = DatabaseFactory.OpenDbConnection()) {
Assert.That(db.Select<ParentObject>(parentId), Has.Count.EqualTo(0));
Assert.That(db.Select<ChildObject>("ParentId = {0}", parentId), Has.Count.EqualTo(0));
}
}
什么工作最终被包裹在一个事务服务呼叫后调用数据库。
[Test]
public void Test_Service_Delete() {
var DatabaseFactory = new OrmLiteConnectionFactory(":memory:", false, SqliteDialect.Provider, true);
int parentId;
using (var db = DatabaseFactory.OpenDbConnection()) {
parentId = db.InsertParam(new ParentObject { name = "Bob" }, true);
db.Insert(new ChildObject { ParentId = parentId, name = "Sam" });
}
var service = Container.Resolve<TestService>();
var response = service.Delete(new DeleteRequestObject(parentId));
using (var db = DatabaseFactory.OpenDbConnection()) {
using (var transaction = db.OpenTransaction()) {
Assert.That(db.Select<ParentObject>(parentId), Has.Count.EqualTo(0));
Assert.That(db.Select<ChildObject>("ParentId = {0}", parentId), Has.Count.EqualTo(0));
}
}
}
我仍然模糊为什么这种解决方法工作,但我想我会记录它的任何人跑到这。