私の問題も同様で、私の検索はここにつながりました。サービスをテストするために単体テストを作成しようとすると、同じ「トランザクションがコマンドの接続に関連付けられていません」という例外が発生していました。私の状況の違いは、(テストしていたサービスで)使用していた唯一のトランザクションが接続を正しく処理していたため、これが適用されるとは思わなかったということです。
(私は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));
}
}
最終的に機能したのは、トランザクションでのサービス呼び出しの後にdb呼び出しをラップすることでした。
[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));
}
}
}
この回避策が機能する理由についてはまだあいまいですが、これに遭遇した他の人のために文書化すると思いました。