初めて使用: Asp.NET MVC、NHibernate(FNH)、Ninject を使用した DI。私は 1 つのデータベースですべてを動作させることができましたが、今は 2 つのデータベース (例のために DB1 と DB2) を使用しようとしています。データベース識別子をキーとする SessionFactory の辞書があります。
コンストラクター インジェクションから要求されている内容に基づいて、正しいセッションを選択する方法がわかりません。私はこれを見たController が Ninjectでどのセッションを制御するかを使用して、同じリポジトリに異なる NHibernate セッション (マルチデータベース) を注入する方法ですが、うまくいきませんでした。
public ProductController(DB1.Model.IRepository<Product> prodRepo, DB2.Model.IRepository<Account> acctRepo)
{
[...]
}
NinjectWebCommon.cs スニペット
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 バインディングを調べましたが、セッションをバインドするときにそれを使用する方法がわかりませんでした。
public ProductController([Name("DB1")]DB1.Model.IRepository<Product> prodRepo, [Name("DB2")]DB2.Model.IRepository<Account> acctRepo)
これは私にとってこれらのテクノロジを使用する最初の試みであるため、私が実践していないことを行っている場合、または懸念される可能性がある場合はお知らせください。私は HttpModule にとどまりたいです。