Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 使用Unity解析当前的NHibernate会话,以便注入到存储库中_Asp.net Mvc_Session_Nhibernate_Dependency Injection_Unity Container - Fatal编程技术网

Asp.net mvc 使用Unity解析当前的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

我有一个多项目MVC 5解决方案,其中NHibernate存储库在
Core.Data
类库中声明,但我的会话管理在Wen API
Core.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
方法。然后,我会在应用程序上创建一个singleton
IUnityContainer
,将其用于
UnityConfig.Register
,并且
Resolve
方法不也需要传递相同的容器吗?是的,很抱歉,我忽略了我正在使用的静态访问和解析方法,现在编辑了它们。Resolve是unity附带的扩展方法(它位于Microsoft.Practices.unity命名空间中的UnityContainerExtensions.cs中)