Asp.net mvc 使用Unity解析当前的NHibernate会话,以便注入到存储库中
我有一个多项目MVC 5解决方案,其中NHibernate存储库在Asp.net mvc 使用Unity解析当前的NHibernate会话,以便注入到存储库中,asp.net-mvc,session,nhibernate,dependency-injection,unity-container,Asp.net Mvc,Session,Nhibernate,Dependency Injection,Unity Container,我有一个多项目MVC 5解决方案,其中NHibernate存储库在Core.Data类库中声明,但我的会话管理在Wen APICore.API项目中。它根据每个请求创建和销毁会话: public override void OnActionExecuting(HttpActionContext actionContext) { // start a session var session = SessionFactory.OpenSession(); CurrentSes
Core.Data
类库中声明,但我的会话管理在Wen APICore.API
项目中。它根据每个请求创建和销毁会话:
public override void OnActionExecuting(HttpActionContext actionContext)
{
// start a session
var session = SessionFactory.OpenSession();
CurrentSessionContext.Bind(session);
session.BeginTransaction();
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
// commit the current session
var session = SessionFactory.GetCurrentSession();
var transaction = session.Transaction;
if (transaction != null && transaction.IsActive)
{
transaction.Commit();
}
session = CurrentSessionContext.Unbind(SessionFactory);
session.Close();
}
现在,当我在控制器操作中实例化存储库时,我希望将此特定会话注入存储库。我怎样才能做到这一点?我可以做一个
BaseRepository:IRepository
,使用一个查找会话的构造函数,但我更希望它被注入。我如何才能做到这一点?这是我们如何做到这一点的一个片段
public class UnityConfig
{
private static readonly Lazy<IUnityContainer> _container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
//easy access to the container from anywhere in the application
public static T Resolve<T>()
{
//uses the Resolve<T> extension method
return GetConfiguredContainer().Resolve<T>();
}
private static void Register(IUnityContainer container)
{
container.RegisterType<IRepository, Repository>(
new InjectionConstructor(new ResolvedParameter<ISession>()));
container.RegisterType<ISession>(new PerRequestLifetimeManager(),
new InjectionFactory(c =>
c.Resolve<ISessionFactory>().OpenSession()
));
container
.RegisterType<ISessionFactory>(
new ContainerControlledLifetimeManager(),
new InjectionFactory(c =>
{
var v =
Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008
.ConnectionString(d => d.FromConnectionStringWithKey("web.config.connection.string.key"))
.ShowSql()
.Dialect<CustomOcMsSqlDialect>())
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<IRepository>()
.Conventions.AddFromAssemblyOf<IRepository>())
.BuildSessionFactory();
return v;
})
);
}
}
public interface IRepository
{
}
public class Repository : IRepository
{
private readonly ISession _session;
public Repository(ISession session)
{
_session = session;
}
}
public class SomeController : Controller
{
public ActionResult SomeAction()
{
var repo = UnityConfig.Resolve<IRepository>();
var dbEntity = repo.Load(123);
return View("SomeView");
}
}
公共类UnityConfig
{
私有静态只读惰性容器=新惰性(()=>
{
var container=new UnityContainer();
注册类型(容器);
返回容器;
});
//从应用程序中的任何位置轻松访问容器
公共静态T解析()
{
//使用解析扩展方法
返回GetConfiguredContainer().Resolve();
}
专用静态无效寄存器(IUnityContainer容器)
{
container.RegisterType(
新的注入构造函数(新的ResolvedParameter());
container.RegisterType(新PerRequestLifetimeManager(),
新注射工厂(c=>
c、 Resolve().OpenSession()
));
容器
.RegisterType(
新建ContainerControlled LifetimeManager(),
新注射工厂(c=>
{
变量v=
fluent.Configure()
.数据库(MsSqlConfiguration.MsSql2008
.ConnectionString(d=>d.FromConnectionStringWithKey(“web.config.connection.string.key”))
.ShowSql()
.方言()
.Mappings(m=>m.FluentMappings.AddFromAssemblyOf())
.Conventions.AddFromAssemblyOf())
.BuildSessionFactory();
返回v;
})
);
}
}
公共接口假定
{
}
公共类存储库:IRepository
{
专用只读会话;
公共存储库(ISession会话)
{
_会话=会话;
}
}
公共类控制器:控制器
{
公共行动结果某些行动()
{
var repo=UnityConfig.Resolve();
var dbEntity=回购债务(123);
返回视图(“SomeView”);
}
}
我们通过unity连接存储库、会话和会话工厂。工厂设置为“集装箱受控”(unity singleton)。会话设置为PerRequest
,因此我们为每个请求获得一个新会话。存储库使用常规的生命周期管理器,因此我们为每个解决方案都会得到一个新的生命周期管理器
通过这种方式,您可以向unity请求存储库,并在整个请求过程中获得相同的会话。它还将在请求结束时自动处理会话。但我相信,如果您愿意,您可以参加ApplicationEndRequest活动,并进行一些室内清洁
希望这有帮助 你看过Unity的PerRequestLifeTime Manager吗?我已经在我们的项目中了解了你的要求,而且都是基于PerRequestLifeTime经理的。也就是说,在容器中注册一个生命周期为“请求”的会话,然后像往常一样从unity解析存储库/会话——实际上每个请求都会获得一个新的会话。今天晚些时候我可以发布更详细的答案。谢谢你,@aeliusd。我可能需要更多的细节。我以前从未使用过NHibernate。在
SomeAction
中,您调用UnityConfig.Resolve()
,但是UnityConfig
没有Resolve
方法。然后,我会在应用程序上创建一个singletonIUnityContainer
,将其用于UnityConfig.Register
,并且Resolve
方法不也需要传递相同的容器吗?是的,很抱歉,我忽略了我正在使用的静态访问和解析方法,现在编辑了它们。Resolve是unity附带的扩展方法(它位于Microsoft.Practices.unity命名空间中的UnityContainerExtensions.cs中)