【问题标题】:How to identify what Session Ninject should bind如何识别 Session Ninject 应该绑定什么
【发布时间】:2013-01-18 13:59:35
【问题描述】:

第一次使用:Asp.NET MVC,NHibernate(FNH),DI使用Ninject。我能够使用一个数据库来完成所有工作,但现在我正在尝试使用两个数据库(例如,DB1 和 DB2)。我有一个 SessionFactory(s) 字典,它以数据库标识符为键。

我不知道如何根据构造函数注入的请求来选择正确的会话。我见过这个How to inject different NHibernate Sessions (multi-db) to same repository with Controller controling which sesions with Ninject,但我没有让它工作。

public ProductController(DB1.Model.IRepository<Product> prodRepo, DB2.Model.IRepository<Account> acctRepo)
{
    [...]
}

NinjectWebCommon.cs sn-p

private static void RegisterServices(IKernel kernel)
{            
    kernel.Bind<ISession>().ToMethod(ctx => NHibernateSessionModule.Provider.GetCurrentSession()).InRequestScope();             
    kernel.Bind(typeof(DB1.Model.IRepository<>)).To(typeof(NHibernateRepository<>));
    kernel.Bind(typeof(DB2.Model.IRepository<>)).To(typeof(NHibernateRepository<>));
}

NHibernateSessionModule.cs:通过 Begin/End 请求执行 UOW

public class NHibernateSessionModule : IHttpModule
{        
    public static ISessionFactoryProvider Provider = new MultipleSessionFactoryProvider();

    public void Dispose() { }

    public void Init(HttpApplication context)
    {
        context.BeginRequest += BeginRequest;
        context.EndRequest += EndRequest;
    }

    public void BeginRequest(object sender, EventArgs e)
    {
        Provider.BindNew();
    }

    public void EndRequest(object sender, EventArgs e)
    {
        Provider.Unbind();
    }
}

MultipleSessionFactoryProvider.cs:不太确定我在这里所做的一切是否正确。

public class MultipleSessionFactoryProvider : ISessionFactoryProvider
{
    public Dictionary<string, ISessionFactory> SessionFactories { get; private set; }

    public static Func<Dictionary<string,ISessionFactory>> InitSessionFactories = GetFactories;

    public MultipleSessionFactoryProvider() : this(InitSessionFactories())
    {

    }

    public MultipleSessionFactoryProvider(Dictionary<string, ISessionFactory> factories)
    {
        SessionFactories = factories;            
    }

    public static Dictionary<string, ISessionFactory> GetFactories()
    {
        Dictionary<string, ISessionFactory> ret = new Dictionary<string, ISessionFactory>();
        Dictionary<string, string> connectionStrings = new Dictionary<string, string>();
        connectionStrings.Add(ConfigurationManager.ConnectionStrings["DB1"].Name, ConfigurationManager.ConnectionStrings["DB1"].ConnectionString.ToString());
        connectionStrings.Add(ConfigurationManager.ConnectionStrings["DB2"].Name, ConfigurationManager.ConnectionStrings["DB2"].ConnectionString.ToString());

        foreach (KeyValuePair<string, string> pair in connectionStrings)
        {
            //Better way to do the mapping?
            ISessionFactory factory = Fluently.Configure()
            .Database(MsSqlConfiguration.MsSql2008.ConnectionString(pair.Value))
            .Mappings(cfg => cfg.FluentMappings.Conventions.Setup(x => x.Add(AutoImport.Never()))
            .AddFromAssemblyOf<ProductMap>())
            .BuildConfiguration()
            .CurrentSessionContext<WebSessionContext>().BuildSessionFactory();               

            ret.Add(pair.Key, factory);
        }

        return ret;
    }

    public void BindNew()
    {
        foreach (KeyValuePair<string, ISessionFactory> factory in SessionFactories)
        {
            Bind(OpenSession(factory.Key));
        }            
    }

    public void Bind(ISession session)
    {
        CurrentSessionContext.Bind(session);
    }

    public void Unbind()
    {            
        foreach (KeyValuePair<string, ISessionFactory> factory in SessionFactories)
        {
            if (CurrentSessionContext.HasBind(factory.Value))
            {
                var sess = CurrentSessionContext.Unbind(factory.Value);
                sess.Dispose(); 
            }
        }
    }

    public ISession OpenSession(string factoryId)
    {
        return SessionFactories[factoryId].OpenSession();
    }


    public ISession GetCurrentSession()
    {

        string factoryId = GetIdentifier(); //<--- How to implement this

        return SessionFactories[factoryId].GetCurrentSession();
    }

    public String GetIdentifier()
    {
        return "DB1"; //Hardcoded for example

    }

那么,我该如何实现GetIdentifier(),或者改变我的 Ninject 绑定。我确实看过 Ninject Named binding,但在绑定 Session 时不明白如何使用它。

public ProductController([Name("DB1")]DB1.Model.IRepository<Product> prodRepo, [Name("DB2")]DB2.Model.IRepository<Account> acctRepo)

由于这是我第一次使用这些技术,如果我在做任何不实践的事情或者可能引起关注的事情,请告诉我;我想继续使用 HttpModule。

【问题讨论】:

  • 请不要将“ASP.NET MVC”简单地称为“MVC”。一种是框架,另一种是与语言无关的设计模式。这就像调用 IE - “互联网”

标签: asp.net-mvc nhibernate ninject


【解决方案1】:

会话需要两个绑定,每个数据库一个

kernel.Bind<ISession>().ToMethod(ctx => GetSessionForDB1()).WhenInjectedInto(typeof(DB1.Model.IRepository<>)).InRequestScope();

kernel.Bind<ISession>().ToMethod(ctx => GetSessionForDB2()).WhenInjectedInto(typeof(DB2.Model.IRepository<>)).InRequestScope();    

【讨论】:

  • 谢谢,这正是我所需要的!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-27
相关资源
最近更新 更多