locked
MVC and Fluent NHibernate. Architecture questions. RRS feed

  • Question

  • User-359210852 posted

    Good afternoon people,  

    I have been playing around with MVC recently and have decided to build a personal website in an attempt to solidify my understanding of larger architectures and how to use Flient Nhibernate properly.  I have gone through several MVC beginners tutorials and have completed them successfully.  However, now it comes to creating a slightly more complex and perhaps more extensible framework, I am encountering several issues.  Specifically with database configuration and where to place certain object.

    Please forgive me for this post is likely to be a lengthy one as id like to provide as much information as possible.

    My site is very simple.  It has only two pages currently; The home page simply shows information about myself and the second page is a collection of projects I have developed in the past.  The idea being any potential employers can visit this site as a substitution for a CV.

    Now im using MVC but have split the Models, Views and Controllers into separate projects, just because all in the same project did not sit well with me.  Below is a rough guideline to my solutions setup:

    My Solution

    • MySolution.Controllers
      • HomeController
      • AccountController    
      • ProjectsController
    • MySolution.DataAccess
      • BaseDao
      • ProjectsDao
    • MySolution.Models
      • DataInterfaces (folder)
        • IBaseDao<T>
        • IProjectDao : IBaseDao<ProjectDao>
      • Entities (objects to be persisted in database)
        • Project
    • MySolution.Tests
      • Pretty obvious what's in here.
    • MySolution.Web (Views / Web.config / CSS / Scripts ect)
      • Content (as standard with MVC)
      • Scripts (as standard with MVC)
      • Views (as standard with MVC)
        • Account (as standard with MVC)
        • Home (as standard with MVC)
        • Projects
          • Projects.aspx (Page to display a list of 'ProjectOverview.ascx')
          • ProjectOverview.ascx (Abstracted view to display project details)
        • Global.asax
        • Web.config


    Ok so now here come my issues.  I am using NHibernate to persist my domain objects in a SQL database.  I am using Fluent NHibernate...because I like it Laughing.  Now I am aware from my university courses and the many blogs I have read over the years that the 'View' tier of an application should be as ignorant as possible to all other elements of the application.  With this in mind, the initial co

    configuration of the NHibernate (database connection and mappings) is contained within the BaseDao constructor as follows:

    public class BaseDAO<T> : IBaseDao<T>
    {
       public BaseDAO(string dbConnectionString)
        {
            var nhConfig = new NHibernate.Cfg.Configuration();
            nhConfig.Properties.Add(NHibernate.Cfg.Environment.ProxyFactoryFactoryClass, typeof(NHibernate.ByteCode.LinFu.ProxyFactoryFactory).AssemblyQualifiedName);
            nhConfig.Properties.Add(NHibernate.Cfg.Environment.ConnectionDriver, typeof(NHibernate.Driver.SqlClientDriver).AssemblyQualifiedName);
            nhConfig.Properties.Add(NHibernate.Cfg.Environment.ConnectionString, dbConnectionString);
            nhConfig.Properties.Add(NHibernate.Cfg.Environment.Dialect, typeof(NHibernate.Dialect.MsSql2008Dialect).AssemblyQualifiedName);
    
            _sessionFactory = Fluently.Configure(nhConfig)
                                        .Mappings(x => x.AutoMappings.Add(AutoMap.AssemblyOf<Project>()
                                                    .Where(t => t.Namespace == typeof(Project).Namespace)))
                                        .ExposeConfiguration(x => new SchemaUpdate(x).Execute(false, true))
                                        .BuildSessionFactory();
        }



    So working from the notion that the view of an application must be ignorant to its underlying model entities, we cannot have this

    configuration code in the view assembly else we would need to add a reference to MySolution.Models for:

    .Mappings(x => x.AutoMappings.Add(AutoMap.AssemblyOf<Project>()
                                                    .Where(t => t.Namespace == typeof(Project).Namespace)))



    to function correctly as 'Project.cs' is contained within the MySolution.Models.Entities namespace. This isn't such an issue until we

    consider that the actual connection string for the required database is contained within the Web.config which resides within the

    view assembly (and as i understand it, that's where it should be).


    So (finally) my question is, how is this typically set up ? All the functionality I have coded works fine in tests, because the testing

    assembly has its own config file. I notice there is a Global.asax within the View assembly, but I dont think my DataAccess layer is

    able to get to that. Another issue I can see arising is that every time a controller creates any kind of Dao object inheriting from this BaseDao

    , its going to configure NHibernate over and over and over again...I smell a static class somewhere but have hit a wall in deciding where this

    should be.


    Any help greatly appreciated, thank you for your time.



     

    Monday, June 7, 2010 10:51 AM

Answers

  • User-2074625069 posted

    Hi Methical,

     

    I have buiilt a similar architecture for a book I am writign which you can check out here: http://aspnetdesignpatterns.codeplex.com/ . I have gone with a Domain Model approach as my application has some domain logic. I have also used NHibernate (although with old skool XML mapping) as my repository implementation. I have a boot strapper class located in the MVC web project and which registers all implementations with the StructureMap IoC Container. To configure  Nhibernate I have an NHibernate SessionFactory that will configure NHibernate the first time its called and only the first time, something like:

        public class SessionFactory
        {
            private static ISessionFactory _SessionFactory;        
    
            private static void Init()
            {
                Configuration config = new Configuration();
                config.AddAssembly("Agathas.Storefront.Repository.NHibernate");
    
                log4net.Config.XmlConfigurator.Configure();            
                
                config.Configure();
    
                _SessionFactory = config.BuildSessionFactory();
            }
    
            private static ISessionFactory GetSessionFactory()
            {
                if (_SessionFactory == null)
                    Init();
    
                return _SessionFactory;
            }
       
          //. ....
    }


     

    Let me know what you think of the architecture, I have included a diagram to make it clear how I have structured the solution.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, June 7, 2010 2:33 PM
  • User-2074625069 posted

    I also notice that your 'view' contains references to your model & DAL as well as a few others.  Doesn't this tie you down to this implementation somewhat ?  If tomorrow, you decided that MVC was not worth the hassle, and wanted to change the site to Silverlight for example, you'd essentially have to re-code half your solution ?  Are any of the assemblies in this solution re-usable to some degree?  Or do you have to start from scratch for each site ?

    The web application which is made up of the Web.MVC project and the Controller project are required for my ASP.NET MVC UI implementation. If you wanted to add a silverlight application or a windows form front end it would be trival as they could all reuse the Service layer, Infrastructure and Repository projects, you would of course have to implement a different presentation logic something like Model-View-Presenter for the Win forms and Model-View-View-Model for the silverlight app, but this makes sense as a win forms app has no need for cookie storage and a silver light app can be stateful - do you see what I mean? The reason for seperating the Web.MVC project and the Controller projects enables a different version of the web site to be created maybe a mobile version of the site in a project like Web.MV.Mobile that would reuse the Controller project.

    The reason that the Web.MVC project has references to the other projects is purely as it ties up the depenedncies. If I wanted to create a site with a different payment service, I would just update the bootstrapper class within the Web.MVC project. If you look at the code there are no calls to any of these assemblies other than for wiring up in the IoC container.

    I realise most of these questions are a result of my lack of understanding.  I see there are 2 web.config files in the view assembly, I cannot find where about in code the connection strings contained within these files are used. 

    I am using an NHibernate implementation of the repositories defined in the Model project, if you take a look in the web.config you will see an NHibernate declaration containing a database connection string.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, June 8, 2010 7:33 AM

All replies

  • User-2074625069 posted

    Hi Methical,

     

    I have buiilt a similar architecture for a book I am writign which you can check out here: http://aspnetdesignpatterns.codeplex.com/ . I have gone with a Domain Model approach as my application has some domain logic. I have also used NHibernate (although with old skool XML mapping) as my repository implementation. I have a boot strapper class located in the MVC web project and which registers all implementations with the StructureMap IoC Container. To configure  Nhibernate I have an NHibernate SessionFactory that will configure NHibernate the first time its called and only the first time, something like:

        public class SessionFactory
        {
            private static ISessionFactory _SessionFactory;        
    
            private static void Init()
            {
                Configuration config = new Configuration();
                config.AddAssembly("Agathas.Storefront.Repository.NHibernate");
    
                log4net.Config.XmlConfigurator.Configure();            
                
                config.Configure();
    
                _SessionFactory = config.BuildSessionFactory();
            }
    
            private static ISessionFactory GetSessionFactory()
            {
                if (_SessionFactory == null)
                    Init();
    
                return _SessionFactory;
            }
       
          //. ....
    }


     

    Let me know what you think of the architecture, I have included a diagram to make it clear how I have structured the solution.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, June 7, 2010 2:33 PM
  • User-359210852 posted

    Thank you for your reply, especially as it includes a solution with it !   I am going to have to go through it a few times.  I have only recently (about a year now) been playing around with web-based solutions and so there is a lot in this solution that I have no understanding of.  At first glance, this seems like A LOT of work and configuration just to get a site up-and-running.  

    I also notice that your 'view' contains references to your model & DAL as well as a few others.  Doesn't this tie you down to this implementation somewhat ?  If tomorrow, you decided that MVC was not worth the hassle, and wanted to change the site to Silverlight for example, you'd essentially have to re-code half your solution ?  Are any of the assemblies in this solution re-usable to some degree?  Or do you have to start from scratch for each site ?

    I realise most of these questions are a result of my lack of understanding.  I see there are 2 web.config files in the view assembly, I cannot find where about in code the connection strings contained within these files are used. 

    Tuesday, June 8, 2010 4:41 AM
  • User-2074625069 posted

    I also notice that your 'view' contains references to your model & DAL as well as a few others.  Doesn't this tie you down to this implementation somewhat ?  If tomorrow, you decided that MVC was not worth the hassle, and wanted to change the site to Silverlight for example, you'd essentially have to re-code half your solution ?  Are any of the assemblies in this solution re-usable to some degree?  Or do you have to start from scratch for each site ?

    The web application which is made up of the Web.MVC project and the Controller project are required for my ASP.NET MVC UI implementation. If you wanted to add a silverlight application or a windows form front end it would be trival as they could all reuse the Service layer, Infrastructure and Repository projects, you would of course have to implement a different presentation logic something like Model-View-Presenter for the Win forms and Model-View-View-Model for the silverlight app, but this makes sense as a win forms app has no need for cookie storage and a silver light app can be stateful - do you see what I mean? The reason for seperating the Web.MVC project and the Controller projects enables a different version of the web site to be created maybe a mobile version of the site in a project like Web.MV.Mobile that would reuse the Controller project.

    The reason that the Web.MVC project has references to the other projects is purely as it ties up the depenedncies. If I wanted to create a site with a different payment service, I would just update the bootstrapper class within the Web.MVC project. If you look at the code there are no calls to any of these assemblies other than for wiring up in the IoC container.

    I realise most of these questions are a result of my lack of understanding.  I see there are 2 web.config files in the view assembly, I cannot find where about in code the connection strings contained within these files are used. 

    I am using an NHibernate implementation of the repositories defined in the Model project, if you take a look in the web.config you will see an NHibernate declaration containing a database connection string.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, June 8, 2010 7:33 AM
  • User-359210852 posted

    Ok yea, im getting you now.  I was getting bogged down with particulars i didn't understand like BootStrappers and AutoMappers.  Didn't see the tree's through the forest so to speak.  


    Since your most recent reply I can see exactly how this answers my question, thank you Laughing

    Tuesday, June 8, 2010 8:12 AM
  • User-2074625069 posted

    No worries, let me know if you have any more questions. 

    Tuesday, June 8, 2010 9:31 AM