Можно ли поместить постоянные сущности NHibernate в один и тот же жизненный цикл сеанса? - PullRequest
1 голос
/ 13 июля 2011

Я хочу поместить постоянные сущности в один и тот же жизненный цикл сеанса NHibernate, возможно ли это?

public class ViewModel
{
    readonly Func<Owned<ISession>> _sessionFactory;

    public ViewModel(Func<Owned<ISession>> sessionFactory)
    {
        _sessionFactory = sessionFactory;
    }

    public void DoSomething()
    {
        using (var session = _sessionFactory())
        {
            using (var trans = session.Value.BeginTransaction())
            {
                session.Value.Get<Model>(1).DoSomething();
                trans.Commit();
            }
        }
    }
}

public class Model
{
    readonly ILifetimeScope _lifetimeScope;

    public Model(ILifetimeScope lifetimeScope)
    {
        _lifetimeScope = lifetimeScope;
    }

    public void DoSomething()
    {
        ISession session = _lifetimeScope.Resolve<ISession>();
        Model model = session.Get<Model>(2);
        model.Text = "test";
    }

    public string Text { get; set; }
}

1 Ответ

2 голосов
/ 13 июля 2011

Способ внедрения конструктора в объекты NHibernate заключается в использовании IInterceptor. От http://www.nhforge.org/doc/nh/en/#objectstate-interceptors

Перехватчики бывают двух видов: ISession-scoped и ISessionFactory-scoped.

Перехватчик в области ISession указывается при открытии сеанса с использованием одного из перегруженных методов ISessionFactory.OpenSession (), принимающих IInterceptor.

ISession session = sf.OpenSession( new AuditInterceptor() );

Похоже, у вас уже настроен контейнер для разрешения сеансов ISession. Вам просто нужно изменить его так, чтобы он имел перехватчик с областью действия, который может создавать экземпляры ваших сущностей. Я мог бы представить что-то вроде этого:

public class AutofacInterceptor : NHibernate.EmptyInterceptor
{
    Autofac.ILifetimeScope scope;

    public AutofacInterceptor(Autofac.ILifetimeScope scope)
    {
        this.scope = scope;
    }

    public override object Instantiate(string entityName, EntityMode entityMode, object id)
    {
        // use the LifetimeScope to instantiate the correct entity
    }
}

И скажите Autofac, что нужно разрешить ISessions с вашим перехватчиком, возможно, так:

builder.Register(c =>
{
    var scope = c.Resolve<ILifetimeScope>();
    var factory = c.Resolve<NHibernate.ISessionFactory>();
    return factory.OpenSession(new AutofacInterceptor(scope));
})
.As<NHibernate.ISession>();

Это не проверено, но я думаю, что это правильный путь. Возможно, вам понадобится или вы захотите определить собственную фабрику сеансов вместо использования Func<Owned<ISession>>.

Примечание: ваш пример показывает, что вы получаете доступ к ISession от вашей сущности. Я думаю, что это необычно. Некоторые люди, , такие как Udi , не любят вводить что-либо в сущности; другие говорят, что вам нужно внедрять сервисы, чтобы избежать анемичной модели предметной области. Но я никогда не видел, как вводить сеанс в сущности.

...