2014-10-29 3 views
0

npoco를 사용하여 트랜잭션 작업을하려고하는데 AbortTransaction 메서드를 db에서 롤백 할 수 없습니다. 테스트 클래스에서왜 AbortTransaction이 작동하지 않습니까?

public class ItemRepository 
{ 
    private Func<Database> _db; 

    public ItemRepository(Func<Database> db) 
    { 
     _db = db; 
    } 

Public void Update(){ 
    using (_db().Transaction) 
    { 
     _db().BeginTransaction(); 
     foreach (var item in itemToUpdate.Items) 
     { 
      _db().Insert(item); 
      if (SomethingIsNotCorrect()) 
      { 
       _db().AbortTransaction(); 
      } 
     } 
    _db().CompleteTransaction(); 
    } 
}} 

전화 :

_db =() => new Database(String.Format("DataSource={0};Persist Security Info=False;", DbPath),"System.Data.SqlServerCe.4.0"); 
_itemRepository = new ItemRepository(() => _db()); 
_itemRepository.Update(); 

------------- 편집 후 제안 답 :

var db = _db(); 
using (db.Transaction) 
{ 
    db.BeginTransaction(); 
    foreach (var item in itemToUpdate.Items) 
    { 
     db.Insert(item); 
     db.Transaction.Commit(); 
     if (GetNutrientConns(itemToUpdate).Count > 2) 
     { 
      db.AbortTransaction(); 
     } 
    } 
    db.CompleteTransaction(); 
} 

는 지금은 DB를 사용해야합니다. Transaction.Commit()는 db에 무언가를 삽입합니다. 그런 다음 db.AbortTransaction()을 실행할 때 오류 메시지가 나타납니다.

"이 SqlCeTransaction이 완료되어 더 이상 사용할 수 없습니다."

+1

_db()는 무엇입니까? 말하지 말아요 새로운 DB 연결을 반환하는 방법입니다 – Reniuz

+0

@ Renenuz, private Func _db; 이 생성자에서 한 번 설정하면 한 번에 같아야합니다. –

+0

@daniel_aren 전에이 라이브러리를 사용한 적이 없지만 한 번 호출하여 결과를 필드 또는 변수에 저장하고 참조해야합니다. 자꾸. –

답변

0

최종 솔루션 업데이트 방법 :

var db = _dbFactory(); 
public void Update() { 
try 
{ 
    db.BeginTransaction(); 
    foreach(item in itemlist) 
    { 
     db.Insert(item); 
    } 
    db.CompleteTransaction(); 
} 
catch(Exception) 
{ 
    db.Transaction.Rollback(); 
} 

예외를 throw하여 테스트 할 때 트랜잭션이 사라지기 때문에 롤백이 예외적으로 필요한지 잘 모르겠습니다.

2

업데이트에서 문제가 무엇인지 명확하게 알 수 있습니다. 새로운 연결/datacontext를 인스턴스화하고 반환하는 팩토리 함수를 생성하여 저장소 생성자에 전달합니다. 여태까지는 그런대로 잘됐다.

그런 다음 팩토리 함수에서 가져온 새로운 Database 인스턴스에서 모든 단일 트랜잭션 관련 호출을 호출합니다. 이는 의미가 없습니다. 생성자에서 팩토리 함수를 사용하여 실제로 Database 인스턴스를 가져오고 필드에 저장하십시오. 필요한만큼 사용하십시오.

public class ItemRepository 
{ 
    private Database _db; 

    public ItemRepository(Func<Database> dbFactory) 
    { 
     _db = dbFactory(); 
    } 

    ... 
} 

UPDATE : 더 데이터 컨텍스트의 범위와 수명을 제한하는 이익, 마이크 C가 지적했듯이, 공장을 저장하고 내 사는 Database 인스턴스를 생성하는 것이 바람직 할 것 Update 방법의 범위, 그래서 같은 :

public class ItemRepository 
{ 
    private Func<Database> _dbFactory; 

    public ItemRepository(Func<Database> dbFactory) 
    { 
     _dbFactory = dbFactory; 
    } 

    public void Update() { 
     var db = _dbFactory(); 

     // Now use db wherever you were using _db() 
     ... 
    } 
} 
+1

또는 OP는 각 메소드의 시작 부분에서 factory 메소드를 호출하고 호출하는 동안 반환 된 인스턴스를 사용할 수 있습니다. 이것은'Update'에 대한 두 번의 호출이 같은 인스턴스를 공유 할 수 없기 때문에 스레드 안전을 보장하는데 도움이됩니다. – mclark1129

+0

@MikeC 그건 중요한 지적입니다. 어느 쪽이든,'Update' 메쏘드에 대한 호출마다 팩토리 함수에 대한 호출은 하나만 있으면 안됩니다. –

+0

@Asas, 죄송 합니다만 도움이되지 않습니다 .. 거래와 함께 npoco가 작동하는 방식을 이해해야합니다. –