Транзакции с использованием Castle AutoTx Facility и NHibernate Facility
Я пытаюсь использовать Castle NHibernate Facility с AutoTx Facility. В качестве теста я выбрасываю исключение в середине моего сервиса, чтобы убедиться, что транзакция откатывается. Тем не менее, данные все еще сохраняются в базе данных.
Мой сервисный интерфейс, 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);
}
}
Наконец, вот как я настраиваю виндзорский контейнер. NHibernateInstaller
прямо из руководства, с моей беглой конфигурацией 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);
Конфигурация казалась довольно простой, но я не могу понять, что мне не хватает. Спасибо за любую помощь.
2 ответа
Вы не показываете код объявления класса для класса реализации сервиса, так что вы, возможно, уже сделали это, но если вы хотите декларативные транзакции, вам нужно аннотировать класс транзакции с помощью [Transactional]
приписывать.
[Transactional]
public class ActivityServiceImpl {
[Transaction]
public Activity CreateActivity(Activity activity) {
// ... implementation here
}
}
Если вы не включите атрибут [Transactional] в реализующий класс, средство AutoTx не знает, как создать оболочку для класса.
Я склонен ставить [Transaction]
атрибут в методе реализации, а не в определении интерфейса. Я не знаю, работает ли это, аннотируя объявление метода интерфейса.
Еще одна вещь, которую вы можете попробовать. Я заметил, что когда вы настраиваете свой контейнер, вы сначала устанавливаете, а затем добавляете средство AutoTx. Я думаю, что вы должны добавить средства, прежде чем вызывать ваши установщики.
Сначала у вас должны быть прямые зависимости между диспетчером сеансов и службой активности. Менеджер сеансов должен быть введен в Activity Service. Только в этом случае средство может повлиять на транзакцию NHibernate.
[Транзакционный] открытый класс ActionService: IActionService { private ISessionManager _sessionManager; [Transaction] public void AddActivity(Activity Activity) { using (сеанс ISession = _sessionManager.OpenSession()) { using (ITransaction tran = session.BeginTransaction()) { session.Save(активность); tran.Commit (); }}} public ActionService (ISessionManager sessionManager) {_sessionManager = sessionManager; }} _container.Register (Component.For().ImplementedBy .LifestylePerWebRequest ());
Также убедитесь, что вы используете одинаковые стили жизни для SessionManager, Server, DAO и других зависимых объектов.