【问题标题】:SQLite under ORMLite doesn't allow any action after transaction if finishedORMLite 下的 SQLite 不允许在事务完成后执行任何操作
【发布时间】:2013-03-20 17:28:49
【问题描述】:

通过 ServiceStack 的 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 的 bug 吗?

【问题讨论】:

    标签: c# sqlite servicestack ormlite-servicestack


    【解决方案1】:

    原来在我当前使用的版本中,reportedfixed 已经出现了类似的问题。在将我的测试与 the passing one 进行比较后,我发现我没有 Dispose() 我的交易。

    最后的答案是:交易必须被处置。如果不是,则在使用 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>());
                }
            }
    

    【讨论】:

      【解决方案2】:

      我的问题是类似的,我的搜索导致这里。尝试编写单元测试来测试我的服务时,我得到了相同的“事务与命令的连接无关”异常。我的情况不同的是,我使用的唯一事务(在我正在测试的服务中)正确处理了它的连接,所以我认为这不适用。

      (我使用的是 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 块中,如下所示:

      using (var db = DatabaseFactory.OpenDbConnection()) {
          using (var transaction = db.BeginTransaction(IsolationLevel.ReadCommitted)) {
              // do stuff here
          }
      }
      

      不过,在调用 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));
              }
          }
      }
      

      我仍然不清楚为什么这种解决方法有效,但我想我会记录下来以供遇到此问题的任何人使用。

      【讨论】:

        猜你喜欢
        • 2023-03-17
        • 1970-01-01
        • 1970-01-01
        • 2020-01-11
        • 1970-01-01
        • 2019-05-17
        • 1970-01-01
        • 1970-01-01
        • 2015-02-16
        相关资源
        最近更新 更多