Транзакции с использованием Castle AutoTx Facility и NHibernate Facility - PullRequest
3 голосов
/ 12 декабря 2011

Я пытаюсь использовать 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 ]

1 голос
/ 15 декабря 2011

Вы не показываете код объявления класса для класса реализации сервиса, так что вы, возможно, уже сделали это, но если вы хотите декларативных транзакций, вам нужно аннотировать класс транзакций атрибутом [Transactional].

[Transactional]    
public class ActivityServiceImpl {

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

Если вы не включите атрибут [Transactional] в реализующий класс, средство AutoTx не знает, как создать оболочку для класса.

Я склонен поставить атрибут [Transaction] наметод реализации, а не в определении интерфейса.Я не знаю, работает ли он, аннотируя объявление метода интерфейса.

Еще одна вещь, которую вам, возможно, придется попробовать.Я замечаю, что когда вы настраиваете свой контейнер, вы сначала устанавливаете, а затем добавляете средство AutoTx.Я думаю, что вы должны добавить средства, прежде чем вызывать ваши установщики.

1 голос
/ 13 декабря 2011

Сначала у вас должны быть прямые зависимости между диспетчером сеансов и службой активности. Менеджер сеансов должен быть введен в 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 и других зависимых объектов.

...