2013-02-12 71 views
0

我有一個BO(國家)與一個孩子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."); 
    } 
} 

Sample project

回答

0

DalManager(和ConnectionManager)依靠引用計數來確定何時關閉實際連接。

規則不確保處理DalManager,因此DalManager和引用計數關閉。導致更新發生在創建並在其中一個提取操作中打開的連接上,因此不會在Update方法的TransactionScope中註冊。

參見:http://msdn.microsoft.com/en-us/library/bb896149%28v=sql.100%29.aspx

的所有規則必須改變,以處置DalManager的。原始規則:

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 is 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

從我的SQL CE和交易的理解,他們只用在一個單一的數據庫連接上支持事務TransactionScope的。

它看起來像你的代碼遵循由CSLA的一些示例提出的模型,但數據庫連接的實際打開/關閉隱藏在GetManager或GetProvider抽象中,因此無法確切地說出如何這是處理。

雖然SQL CE似乎對TransactionScope的事務有一些限制,但是您應該確保您不會以某種方式違反其中的某個限制。

+0

我在里昂證券論壇的答案,你是在正確的軌道上。在我的商業規則中,我沒有正確處理DalManager導致問題。 – Mensur 2013-02-13 13:55:32