Транзакции с использованием 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 и других зависимых объектов.

Другие вопросы по тегам