0

私はリポジトリパターンを使用しようとしています。流暢なnhibernateを持つDI用のninjectです。流暢なnhibernateでリポジトリを設定するにはどうすればよいですか?

私は、だから私はセットアップこれまでを持っている3つのプロジェクト

web ui - controllers,view (I am using asp.net mvc 2.0) 
framework - repository, domain, fluent mapping 
tests - where my unit tests will go. 

に私の解決策を解体します。

Global.aspx

protected void Application_Start() 
     { 
      AreaRegistration.RegisterAllAreas(); 

      RegisterRoutes(RouteTable.Routes); 

      ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory()); 
     } 

だから私はninjectコントローラの工場の使用を開始する自分のアプリケーションに置きます。

NinjectControllerFactoryここに私のセットアップ私のninjectもの

public class NinjectControllerFactory : DefaultControllerFactory 
    { 
     // A Ninject "kernel" is the thing that can supply object instances 
     private IKernel kernel = new StandardKernel(new T4GDemoSevice()); 

     // ASP.NET MVC calls this to get the controller for each request 
     protected override IController GetControllerInstance(RequestContext context, Type controllerType) 
     { 
      if (controllerType == null) 
       return null; 
      return (IController)kernel.Get(controllerType); 
     } 

     // Configures how abstract service types are mapped to concrete implementations 
     private class DemoSevice : NinjectModule 
     { 
      public override void Load() 
      { 
       Bind<ISessionFactory>().ToMethod(c => GetSessionFactory()).InSingletonScope(); 
       Bind<ISession>().ToMethod(c => c.Kernel.Get<ISessionFactory>().OpenSession()).InRequestScope(); 
       Bind<IUsers>().To<UsersRepo>().WithConstructorArgument("session",GetSessionFactory()); 
      } 

      public static ISessionFactory GetSessionFactory() 
      { 
       return Fluently.Configure() 
        .Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("test"))) 
        .Mappings(m => m.FluentMappings.AddFromAssemblyOf<T4G_Demo.Framework.Data.NhibernateMapping.UserMap>()) 
        .BuildSessionFactory(); 
      } 

     } 
    } 

。私は流暢を設定する方法を作った。私は理解しているので、これはWebリクエストごとに1回しか発生しません(これはアプリケーション起動時に呼び出されるためだと思います)。

私のGetSessionFactoryメソッドを静的にする必要があるかどうかはわかりません。

次に、私のIUsersインターフェイスを自分のUserRepoにバインドし、コンストラクタ引数を渡します。私は、私のReposが何かをするためにnhibernateのセッションを必要としていると推測しています。だから私はそれを私のレポにどのように渡すのか分からなかった。

私はそれぞれのリポジトリが構成になると間違っているかもしれないと思いますか?

リポジトリ

public class UsersRepo : IUsers 
    { 
     private ISessionFactory session; 
     public UsersRepo(ISessionFactory session) 
     { 
      this.session = session; 
     } 

     public void CreateUser(Domain.Users newUser) 
     { 
      var openSession = session.OpenSession(); 
      var transaction = openSession.BeginTransaction(); 
      openSession.SaveOrUpdate(newUser); 
      transaction.Commit(); 
     } 
    } 

私はリポジトリを作ってみましたが、再び私はセッションでそれを行う方法がわからないです。私はそれを開いて取引を始めなければならないのです。それが他のどこかで行われるべきかどうかはわかりません。

また、メソッドを実行した後に処理する必要があるかどうかもわかりませんでした。私は人々がapplication_end()メソッドを処理しているのを見ました。

マイホームコントローラー

private IUsers usersRepository; 

     public HomeController(IUsers usersRepository) 
     { 
      this.usersRepository = usersRepository; 
     } 

     public ActionResult Index() 
     { 
      Users test = new Users() 
      { 
       OpenIdIdentifier = "123", 
       Email = "[email protected]", 

      }; 

      usersRepository.CreateUser(test); 

      return View(); 
     } 

は、最後に私はダミーのユーザーを作成し、DBに挿入するダミーのコントローラを作りました。それは動作しますが、私はセッションの部分が私に混乱させると言ったように、どうやってそれを渡すのか分かりません。

編集

これは私がこれまでに出ているものです。それはまだ私が望むものではない(私はむしろリクエストごとにセッションを持っている)が、動作しているようだ。

Ninject工場

public static ISessionFactory GetSessionFactory() 
     { 
      if (session == null) 
      { 
       return Fluently.Configure() 
       .Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("test"))) 
       .Mappings(m => m.FluentMappings.AddFromAssemblyOf<T4G_Demo.Framework.Data.NhibernateMapping.UserMap>()) 
       //.ExposeConfiguration(BuidSchema) 
       .BuildSessionFactory(); 


      } 

      return session;    
     } 

声明場合、私は、セッションが開始されているかどうかチェックするためにAを追加しました。だから、これは毎回SessionFactoryを起動する問題を処理するはずです。

私のレポは、だから私はない、私はこの方法で1を開いた場合、セッションが開いているかどうかを確認それぞれの方法でこの

public class UsersRepo : IUsers 
    { 
     private ISession openSession; 
     private ISessionFactory session; 
     public UsersRepo(ISessionFactory session) 
     { 
      this.openSession = session.OpenSession(); 
      this.session = session; 
     } 

     public void CreateUser(Users newUser) 
     { 
      openSession = NhibernateUtilities.OpenIfClosed(session, openSession); 
      openSession.SaveOrUpdate(newUser);   
     } 

     public Users GetUser(Guid userId) 
     { 
      openSession = NhibernateUtilities.OpenIfClosed(session, openSession); 
      var query = from b in openSession.Query<Users>() 
         where b.UserId == userId 
         select b; 
      return query.SingleOrDefault(); 
     } 

     public void DeleteUser(Users user) 
     { 
      openSession = NhibernateUtilities.OpenIfClosed(session, openSession); 
      openSession.Delete(user); 
     } 

     public void SaveOrUpdate() 
     { 
      using (openSession) 
      { 
       using (var transaction = openSession.BeginTransaction()) 
       { 
        transaction.Commit(); 
       } 
      } 
     } 

のように見えます。

public static ISession OpenIfClosed(ISessionFactory session, ISession openSession) 
     { 
      if (openSession.IsOpen == false) 
      { 
       return session.OpenSession(); 
      } 

      return openSession; 
     } 

私はこの方法を取り除きたいと言っていましたが、私はセッションをreposに渡す方法がわかりません。誰かが私にそれを見せるまで、私は今のようにそれをしなければならないと思います。

答えて

3

最初にNinjectControllerFactoryとNinjectHttpApplicationが既に用意されているため、Ninject.Web.Mvc拡張機能の使用を検討することもできます。これにより、アプリケーション内にIKernelを作成することができます。これは、コントローラファクトリではなく、必要な場所です。

第2に、SessionFactoryは非常に高価ですので、アプリケーションの存続期間(つまりシングルトン)の間だけ1回行う必要があります。ここ

は、私は私のアプリケーションで使用しているモジュールである。関心の

public class RepositoriesModule : Ninject.Modules.NinjectModule 
{ 
    public override void Load() 
    { 
     // NHibernate 
     Bind<ISessionFactory>().ToProvider<SessionFactoryBuilder>() 
      .InSingletonScope(); 

     Bind<ISession>() 
      .ToMethod(CreateSession) 
      .InRequestScope(); 

     // Model Repositories 
     Bind(typeof(IRepository<>)).To(typeof(NHibernateRepository<>)).InScope(HttpOrThread); 
     Bind<IGameRepository>().To<GameRepository>(); 
     Bind<ILogRepository>().To<LogRepository>(); 
     Bind<IMemberRepository>().To<MemberRepository>(); 

     Bind<IScopeManager>().To<ScopeManager>(); 
    } 

    private ISession CreateSession(Ninject.Activation.IContext context) 
    { 
     var session = context.Kernel.Get<ISessionFactory>().OpenSession(); 
     session.EnableFilter(DigitalLights.Model.FluentLogicalDeleteFilter.FilterName); 
     return session; 
    } 

} 

ポイント - ISessionFactoryはシングルトンスコープでプロバイダに接続されています。プロバイダーシンプルは起動時に一度SessionFactoryを作成します。プロバイダは次のようになります。

/// <summary> 
/// factory builder that uses FluentNHibernate to configure and return a SessionFactory 
/// </summary> 
public class SessionFactoryBuilder : Ninject.Activation.IProvider 
{ 
    private ISessionFactory _sessionFactory; 

    /// <summary> 
    /// constructor configures a SessionFactory based on the configuration passed in 
    /// </summary> 
    /// <param name="configuration"></param> 
    public SessionFactoryBuilder() 
    { 
     /// setup configuration here 

     var fluentConfig = Fluently.Configure() 
      .Database(MsSqlConfiguration.MsSql2005.ConnectionString(connectionString)); 

     this._sessionFactory = fluentConfig.BuildSessionFactory(); 
    } 

    #region IProvider Members 

    public object Create(Ninject.Activation.IContext context) 
    { 
     return _sessionFactory; 
    } 

    public Type Type 
    { 
     get { return typeof(ISessionFactory); } 
    } 

    #endregion 
} 

次に、NHibernateのISessionは、カーネルからISessionFactoryを取得するCreateSessionメソッドによって作成されます。 ISessionは要求にスコープされます。リポジトリの実装は、単にそのコンストラクタ内のSessionを要求します。

また、私のアプリケーションでは、BeginRequestでITransactionが開始され、EndRequestでITransactionがコミットされ、セッションが永続化され、閉じられていることが確認されます。

+0

ええと、最初はIkernalがコントローラにない。私はpro asp.net mvc 2.0の作者がどこに置いたかを追っていた。私はSessionFactoryが作成するのに高価であることを認識しています。私はそれをapplication_startに入れることを私が考えていたのは、一度だけ作成する必要があったからです。私も混乱していますが、このコードがすべてあなたのwebuiプロジェクトにこれから行くのですか?非常に簡単なプロジェクトを見ることができるので、私はデバッガでそれを歩くことができますか?例えば、私はリポジトリがコンストラクタ内でそのセッションを要求している場所や場所を見ていません。 – chobo2

関連する問題