Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

In order to create loose coupling architecture on my web applications, I have created my own implementation for orm, in this case, nhibernate.
I want you please to review the code and tell me if you think it can work in a real world on high traffic app.
I have divided the api to transaction and session. there are some cases where I want to use session with out transaction, and there are times when I need multiple transaction in a single http request.

This is the session Api:

public interface IDalSession : IDisposable 
{
    IDalSession Start();
    IDalTransaction StartWithTransaction();
    bool IsActive();

    T Save<T>(T entity);
    IQueryOver<T> QueryOver<T>() where T : class;
    IQueryable<T> Query<T>() where T : class;
    T CreateQuery<T>(string query) where T : class;
    void ExecuteUpdate(string sqlQuery);
}

This is the trnasaction api

public interface IDalTransaction : IDisposable
    {
        bool IsActive { get; }
        void MarkForRollBack();
        void Commit();

        T Save<T>(T entity);
        IQueryOver<T> QueryOver<T>() where T : class;
        IQueryable<T> Query<T>() where T : class;
        T CreateQuery<T>(string query) where T : class;
        void ExecuteUpdate(string sqlQuery);
    }

This is the session factory (the session suppose to exist per http request): I am aware that I am coupled with the mysql call bellow, will be removed

public class NHibernateSessionFactory
    {
        public static ISessionFactory SessionFactory;

        public static void Configure(DatabaseConnectionProperties database)
        {
            if (SessionFactory == null)
            {
                FluentConfiguration configuration;
                configuration = Fluently.Configure().Database(
                    MySQLConfiguration.Standard.ConnectionString(
                        mysql =>
                        mysql.Database(database.DatabaseName).Username(database.UserName).Password(database.Password).
                            Server(database.Host)
                        ));

                foreach (Type entity in database.Entities)
                {
                    configuration.Mappings(m => m.FluentMappings.AddFromAssembly(entity.Assembly)
                                                    .Conventions.Add(new LowerCaseWithUnderConvention())

                        );
                }
                if (database.GenerateTables)
                {
                    configuration.ExposeConfiguration(cfg => new SchemaExport(cfg).Create(true, true));
                }
                else
                {
                    configuration.ExposeConfiguration(cfg => new SchemaExport(cfg));
                }
                configuration.ExposeConfiguration(
                    c => c.SetProperty("current_session_context_class", "web"));

                SessionFactory = configuration.BuildSessionFactory();
            }
        }

        public static ISession GetCurrentSession()
        {
            if (!CurrentSessionContext.HasBind(SessionFactory))
            {
                CurrentSessionContext.Bind(SessionFactory.OpenSession());
            }
            return SessionFactory.GetCurrentSession();
        }

        public static IDalSession OpenSession()
        {
            return new DalSession(SessionFactory);
        }

        public static void CloseSession()
        {
            SessionFactory.Close();
        }
    }

This is how I inject the session per request

   kernel.Bind<IDalSession>()
            .ToProvider<HttpDalSessionProvider>()
            .InRequestScope();

this is how I provide it to Ninject:

public class HttpDalSessionProvider : Provider<IDalSession>
    {
        private static DatabaseConnectionProperties GetDatabaseConnectionProperties()
        {
            List<Type> entities = new List<Type> {typeof (BillingInfo)};
            return new DatabaseConnectionProperties(
                ConfigurationManager.AppSettings["DbHost"],
                ConfigurationManager.AppSettings["DbName"],
                ConfigurationManager.AppSettings["DbUser"],
                ConfigurationManager.AppSettings["DbPassword"],
                entities,true
                );
        }
        protected override IDalSession CreateInstance(IContext context)
        {
            NHibernateSessionFactory.Configure(GetDatabaseConnectionProperties());
            return NHibernateSessionFactory.OpenSession().Start();
        }
    }

BTW, I could not find the correct tags for this question. Thanks

share|improve this question
add comment

1 Answer 1

I've seen many attempts to abstract particular ORM from application, and all of them at a certain stage of maturity had to break this abstraction. One of the reasons for that is when you need to optimize certain use cases (like eager-loading related entities, or combining several round trips to server into one) you'll need to use ORM specifics that you're abstracting from.

And another (more obvious) reason why I vote against abstracting ORMs from the code is that ORM is already an abstraction, so what you do is an abstraction on top of another abstraction that brings little benefits.

There is a very good series of articles that describes best practices for managing NHibernate in ASP.NET:

share|improve this answer
    
Thank you, please note that this is not an abstract implementation, this is a wrapper. I just want to avoid external dependencies across my systems. –  yos mishan Jan 19 '13 at 4:42
    
I meant exactly that: you are trying to abstract your system from NHibernate –  almaz Jan 19 '13 at 6:47
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.