使用Unity解析当前的NHibernate会话以注入存储库

时间:2015-11-24 05:19:40

标签: asp.net-mvc session nhibernate dependency-injection unity-container

我有一个多项目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<T>: IRepository<T>,但我真的很喜欢它注入。我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:1)

这是我们如何做的片段。

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

我们通过统一连接存储库,会话和会话工厂。工厂设置为ContainerControlled(统一单身)。会话设置为PerRequest,因此我们为每个请求获取一个新会话。并且存储库使用常规生命周期管理器,因此我们为每个解析获得一个新的。

通过这种方式,您可以对存储库请求统一,并在整个请求中获得相同的会话。它还将在请求结束时自动处理会话。但我相信你可以参加ApplicationEndRequest活动并做一些大扫除,如果你想要的话。

希望这有帮助!