是否有可能将NHibernate持久化实体放入会话的同一生命周期中?

时间:2011-07-12 21:02:18

标签: c# nhibernate autofac

我想将持久化实体放在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 个答案:

答案 0 :(得分:2)

对NHibernate实体进行构造函数注入的方法是使用IInterceptor。来自http://www.nhforge.org/doc/nh/en/#objectstate-interceptors

  

拦截器分为两种:ISession-scoped和ISessionFactory-scoped。

     

使用其中一个接受IInterceptor的重载ISessionFactory.OpenSession()方法打开会话时,指定了ISession范围的拦截器。

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

看起来您已经设置了容器来解决ISessions。您只需要更改它,以便它具有可以实例化您的实体的范围拦截器。我想象这样的事情:

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。我觉得这很不寻常。有些人like Udi不喜欢向实体注入任何东西;其他人说你需要注入服务以避免贫血的域模型。但我从未见过将会话注入实体。