2
\$\begingroup\$

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 transaction 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 below; it 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();
 }
 }
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Jan 16, 2013 at 17:30
\$\endgroup\$

1 Answer 1

5
\$\begingroup\$

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:

answered Jan 17, 2013 at 13:11
\$\endgroup\$
2
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Jan 19, 2013 at 4:42
  • \$\begingroup\$ I meant exactly that: you are trying to abstract your system from NHibernate \$\endgroup\$ Commented Jan 19, 2013 at 6:47

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.