我想将持久化实体放在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; }
}
答案 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不喜欢向实体注入任何东西;其他人说你需要注入服务以避免贫血的域模型。但我从未见过将会话注入实体。