2013-03-20 5 views
4

После того, как я создал и совершил транзакцию в SQLite через OrmLite ServiceStack, я не могу продолжать и вызывать какие-либо запросы.SQLite под ORMLite не разрешает никаких действий после транзакции, если завершено

Например, следующий тест не пройден:

 [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; }} 

Исключение я получаю: «сделка не связана с подключением командования в» отсутствии вокруг that line из OrmLite. Однако я вообще не должен быть в сделке.

Когда я использую 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?

ответ

7

Оказалось, что подобная проблема уже была reported и fixed в версии, которую я сейчас использую. После сравнения моего теста с 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 (var db = DatabaseFactory.OpenDbConnection()) { 
    using (var transaction = db.BeginTransaction(IsolationLevel.ReadCommitted)) { 
     // do stuff here 
    } 
} 

Тем не менее, «сделка не связана с подключением к данной команды» исключение ш как бросается на первую строку после вызова службы. Убейте.

Моя первая попытка решить (который не работал) был такой:

[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)); 
     } 
    } 
} 

Я все еще нечеткое на ЗАЧЕМ этот обходной путь работал, но я решил задокументировать это для тех, кто еще работает в этом.