【问题标题】:Use Unity to resolve current NHibernate session for injection into Repositories使用 Unity 解析当前 NHibernate 会话以注入存储库
【发布时间】:2016-02-26 10:34:51
【问题描述】:

我有一个多项目 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>,用一个构造函数找到会话,但我真的更喜欢注入它。我怎样才能做到这一点?

【问题讨论】:

  • 你看过 Unity 的 PerRequestLifetimeManager 了吗?我已经在我们的项目中得到了您的要求,这一切都基于 PerRequestLifetimeManager。即,在具有“请求”生命周期的容器中注册会话,然后像往常一样从统一解析存储库/会话 - 实际上每个请求都会获得一个新会话。我可以在今天晚些时候发布更详细的答案。
  • 谢谢你,@aeliusd。我可能需要更多细节。我以前从未使用过 NHibernate。

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


【解决方案1】:

这是我们如何做的一个 sn-p。

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(unity singleton)。会话设置为PerRequest,因此我们为每个请求获取一个新会话。并且存储库使用常规生命周期管理器,因此我们为每个解析获取一个新的。

通过这种方式,您可以向 unity 请求存储库并在整个请求中获得相同的会话。它还将在请求结束时自动处理会话。但我敢肯定,如果你愿意,你也可以加入 ApplicationEndRequest 事件并进行一些大扫除。

希望这会有所帮助!

【讨论】:

  • 在您的SomeAction 中调用UnityConfig.Resolve&lt;IRepository&gt;(),但UnityConfig 没有Resolve 方法。然后,我会在应用程序上创建一个单例IUnityContainer,将其用于UnityConfig.Register,并且Resolve 方法是否也需要传递同一个容器?
  • 是的,对不起,我省略了我正在使用的静态访问和解析方法,现在编辑它们。 Resolve 是 unity 自带的扩展方法(在 Microsoft.Practices.Unity 命名空间的 UnityContainerExtensions.cs 中)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-20
  • 1970-01-01
  • 2013-02-16
相关资源
最近更新 更多