2013-02-12 2 views
0

저는 BO (City)가있는 BO (국가)와 BO (국가)가 있습니다. 부모 BO (국가)를 업데이트하고 하위 상태를 추가하고 저장을 실행하면 DAL에서 예외가 발생하면 트랜잭션이 롤백되지 않습니다. 나는 SqlCE를 사용하고있다. 문제를 보여주는 샘플을 벗긴 샘플을 첨부하고 있습니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?예외가 발생하면 TransactionScope가 롤백되지 않습니다. CSLA 4.3

테스트 코드 : 사용하는 경우

Country originalCountry = null; 
    try 
    { 
     originalCountry = Country.GetCountry(1); 
     var country = Country.GetCountry(1); 
     country.CountryName = "My new name"; 
     var state = country.States.AddNew(); 
     state.StateName = "Dummy state"; 
     country.States.EndNew(country.States.IndexOf(state)); 
     country.Save(); 
    } 
    catch (Exception exception) 
    { 
     var country = Country.GetCountry(1); 
     if (originalCountry.CountryName != country.CountryName) 
     { 
      System.Console.WriteLine("Values ARE NOT the same: " + originalCountry.CountryName + " vs. " + country.CountryName); 
     } 
     else 
     { 
      System.Console.WriteLine("Values are the same: " + originalCountry.CountryName + " vs. " + country.CountryName); 
     } 
    } 

Country.cs

[Transactional(TransactionalTypes.TransactionScope)] 
protected override void DataPortal_Update() 
{ 
    Update(); 
} 

private void Update() 
{ 
    using (var ctx = DalFactory.GetManager()) 
    { 
     var dal = ctx.GetProvider<ICountryDal>(); 
     using (BypassPropertyChecks) 
     { 
      var dto = new CountryDto(); 
      TransferToDto(dto); 
      dal.Update(dto); 
     } 
     FieldManager.UpdateChildren(this); 
     throw new Exception("Rollback should occur."); 
    } 
} 
SQL CE 및 거래에 대한 이해에서

Sample project

답변

0

DalManager (및 ConnectionManager)는 참조 연결을 사용하여 실제 연결을 닫는 시점을 결정합니다.

규칙에 따라 DalManager가 삭제되지 않으므로 DalManager와 참조 계산이 해제되어 있습니다. 가져 오기 작업 중 하나에서 생성 및 열려진 연결에서 업데이트가 발생하므로 Update 메서드의 TransactionScope에 참여하지 않습니다.

보기 : 모든 규칙이 DalManager 처분을 변경해야합니다 http://msdn.microsoft.com/en-us/library/bb896149%28v=sql.100%29.aspx

. 원본 규칙 :

protected override void Execute(RuleContext context) 
    { 
     var name = (string)context.InputPropertyValues[_nameProperty]; 
     var id = (int)context.InputPropertyValues[_idProperty]; 
     var dal = DalFactory.GetManager(); 
     var countryDal = dal.GetProvider<ICountryDal>(); 
     var exists = countryDal.Exists(id, name); 
     if (exists) 
     { 
      context.AddErrorResult("Country with the same name already exists in the database."); 
     } 
    } 

DalManager는 IDisposable이지만 GC가 실제로 개체를 수집 할 시점에 따라 명시 적으로 여기에 배치되지 않습니다.

은 다음과 같아야합니다

protected override void Execute(RuleContext context) 
    { 
     var name = (string)context.InputPropertyValues[_nameProperty]; 
     var id = (int)context.InputPropertyValues[_idProperty]; 
     using (var dal = DalFactory.GetManager()) 
     { 
      var countryDal = dal.GetProvider<ICountryDal>(); 
      var exists = countryDal.Exists(id, name); 
      if (exists) 
      { 
       context.AddErrorResult("Country with the same name already exists in the database."); 
      } 
     } 
    } 
1

, 그들은 단지 하나의 데이터베이스 연결에 트랜잭션을 지원 TransactionScope.

코드가 CSLA 샘플의 일부 모델을 따르고있는 것처럼 보입니다. 그러나 데이터베이스 연결의 실제 열기/닫기는 GetManager 또는 GetProvider 추상화에 숨겨져 있으므로 어떻게 말 할 것인지는 확실하지 않습니다. 처리 됐어.

SQL CE에는 TransactionScope와의 트랜잭션에 몇 가지 제한 사항이있는 것 같습니다. 따라서 제한 사항 중 하나를 어떻게 든 위반하지 않도록해야합니다.

+0

은 내가 CSLA 포럼에서 답을 얻고 당신은 바로 트랙에 있습니다. 내 비즈니스 규칙에서 DalManager를 적절하게 폐기하지 않아서 문제가 발생했습니다. – Mensur

관련 문제