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.
精彩评论