开发者

Is it possible to put NHibernate persistent entities to the same lifetimescope of session?

开发者 https://www.devze.com 2023-03-20 01:22 出处:网络
I want to put the persistent entities to the same lifetimescope of the NHibernate session, is it possible?

I want to put the persistent entities to the same lifetimescope of the NHibernate session, is it possible?

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; }
}


The way to do constructor injection into NHibernate entities is to use an IInterceptor. From http://www.nhforge.org/doc/nh/en/#objectstate-interceptors

Interceptors come in two flavors: ISession-scoped and ISessionFactory-scoped.

An ISession-scoped interceptor is specified when a session is opened using one of the overloaded ISessionFactory.OpenSession() methods accepting an IInterceptor.

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

It looks like you already have the container set up to resolve ISessions. You just need to change it so that it has a scoped interceptor that can instantiate your entities. I'd imagine something like this:

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
    }
}

And tell Autofac to resolve ISessions with your interceptor, maybe like this:

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

This is untested, but I think it's the right track. You may need or want to define your own session factory rather than using Func<Owned<ISession>>.

A side note: your example shows you accessing the ISession from your entity. I think this is unusual. Some people, like Udi, don't like to inject anything into entities; others say you need to inject services to avoid an anemic domain model. But I've never seen injecting the session into entities.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号