3

我正在嘗試將Castle NHibernate Facility與AutoTx設施配合使用。作爲測試,我在服務中間拋出一個異常,以確保事務回滾。但是,數據仍然保留在數據庫中。使用城堡AutoTx設施和NHibernate設施的交易

我的服務接口,IActivityService使用TransactionAttribute:

public interface IActivityService 
{ 
    [Transaction] 
    Activity CreateActivity(Activity activity); 
} 

CreateActivity實施。我在這裏拋出一個異常,預計在AddActivity添加的數據回滾:

public virtual Activity CreateActivity(Activity activity) 
{ 
    activityDAO.AddActivity(activity); 
    throw new Exception("This should rollback the transaction"); 
    return activity; 
} 

AddActivity實現。 SessionManager是注入的ISessionManager

public void AddActivity(Activity activity) 
{ 
    using (ISession session = SessionManager.OpenSession()) 
    { 
     session.Save(activity); 
    } 
} 

最後,這裏是我如何配置windsor容器。該NHibernateInstaller是直接從the guide,用我的功能NHibernate配置交換:

container = new WindsorContainer().Install(FromAssembly.This()); 

// set up ISessionManager injection for DAOs 
container 
    .AddFacility<AutoTxFacility>() 
    .Register(Component 
     .For<INHibernateInstaller>() 
     .ImplementedBy<NHibernateInstaller>() 
     .LifeStyle.Singleton) 
    .AddFacility<NHibernateFacility>(f => 
     f.DefaultLifeStyle = DefaultSessionLifeStyleOption.SessionPerWebRequest); 

的配置似乎相當簡單,但我想不出什麼我失蹤。謝謝你的幫助。

回答

1

您不顯示服務實現類的類聲明代碼,因此您可能已經完成了此操作,但是如果要聲明事務,則需要使用[Transactional]屬性註釋事務類。

[Transactional]  
public class ActivityServiceImpl { 

    [Transaction] 
    public Activity CreateActivity(Activity activity) { 
     // ... implementation here 
    } 
} 

如果您未在實現類中包含[Transactional]屬性,則AutoTx設施不知道爲該類創建包裝。

我傾向於將[Transaction]屬性放在實現方法上,而不是在接口定義中。我不知道它是否工作註解接口方法聲明。

還有一件事你可能需要嘗試。我注意到,當你配置你的容器時,你首先安裝,然後添加AutoTx工具。我想你應該在調用安裝程序之前先添加這些設備。

+1

啊,你說的對,有兩點,謝謝!我必須在調用安裝程序之前添加這些設施,並且'[Transaction]'必須在實現中。只是一個側面說明,'[Transactional]'屬性已被棄用(我正在運行Castle.Services.Transaction.3.0.202.2202);沒有它就能正常工作。 – Will

1

首先,您必須在會話管理器和活動服務之間有直接的依賴關係。會話管理器應注入到Activity Service中。只有在這種情況下,設施才能影響NHibernate事務。

 
    [Transactional] 
    public class ActionService : IActionService 
    { 
     private ISessionManager _sessionManager; 

     [Transaction] 
     public void AddActivity(Activity activity) 
     { 
      using (ISession session = _sessionManager.OpenSession()) 
      { 
       using (ITransaction tran = session.BeginTransaction()) 
       { 
         session.Save(activity); 
        tran.Commit(); 
       } 
      }  
     } 
     public ActionService(ISessionManager sessionManager) 
    { 
      _sessionManager = sessionManager;  
     } 
    } 
    _container.Register(Component.For<IActionService>() 
      .ImplementedBy<ActionService>.LifestylePerWebRequest()); 

此外,請檢查您是否對SessionManager,Server,DAO和其他相關對象使用相同的生活方式。

+0

感謝您的回覆。在您的示例中,我看到您正在手動管理事務。不應該使用AutoTx設施意味着我不需要那個? – Will

+0

我再次檢查了城堡源,我沒有看到任何NHibernate事務可管理性集成。文檔說:「這個工具通常與其他工具一起工作,因爲它需要實施ITransactionManager。目前ActiveRecord集成工具,NHibernate工具和iBatis.Net工具都實現了ITransactionManager。」但NHibernate的設施並沒有實現一些,它只在容器中註冊DefaultTransactionManager。你可以用nhprof實用程序來檢查它:它會說你「不鼓勵使用隱式事務」。 –