Friday, February 13, 2015

Single Unit of Work pattern -NHibernate and Repository pattern - using structure map



Repository Defined:

Repostiory is of Generic type because the registry can have different type for Informix/SQL and DB2. So those type of repository needs to be created.

public class Repository<T1> : IRepository<T1> where T1 : DatabaseEngine
        {
                private ISession _session { get; set; }

                public Repository(IContainer container)
                {
                        var db = (typeof(T1).ToString());
                        _session = container.GetInstance<ISession>(db);
                }

                public T Get<T>(Expression<Func<T, bool>> predicate)
                {
            if (_session == null) { return default(T); }
                        return _session.Query<T>().Where(predicate).FirstOrDefault();
                }

                public IQueryable<T> Find<T>(Expression<Func<T, bool>> predicate)
                {
            if (_session == null) { return new List<T>().AsQueryable(); }
                        return _session.Query<T>().Where(predicate);
                }

                public IQueryable<T> FindAll<T>()
                {
            if (_session == null) { return new List<T>().AsQueryable(); }
                        return _session.Query<T>();
                }

        public IList<T> ExecuteStoredProcedure<T>(string queryName, params object[] parameters)
        {
            if (_session == null) { return new List<T>().ToList(); }
            return _session.GetNamedQuery(queryName)
                .SetParameterList("parameters", parameters)
                .List<T>();
        }

                public T ExecuteXMLQueryScalarStoredProcedure<T>(string queryName, decimal CRC, string userID, string countryCode, string languageCode, string groups, int sitemapAttr)
                {
            if (_session == null) { return default(T); }
            return _session.GetNamedQuery(queryName)
                                .SetParameter("crc", CRC)
                .SetAnsiString("userid", userID)
                .SetAnsiString("country", countryCode)
                .SetAnsiString("lang", languageCode)
                .SetAnsiString("groups", groups)
                                .SetParameter("sitemap_attribute", sitemapAttr)
                                .UniqueResult<T>();
                }

                public T ExecuteScalarStoredProcedure<T>(string queryName, params object[] parameters)
                {
            if (_session == null) { return default(T); }
            return _session.GetNamedQuery(queryName)
                                .SetParameterList("parameters", parameters)
                                .UniqueResult<T>();
                }

        public T ExecuteScalarStoredProcedure<T>(string queryName)
        {
            if (_session == null) { return default(T); }
            return _session.GetNamedQuery(queryName)
                .UniqueResult<T>();
        }
       public void ExecuteNonQuery(string queryName, params object[] parameters)
        {
             _session.GetNamedQuery(queryName)
                 .SetParameterList("parameters", parameters).ExecuteUpdate();
             SubmitChanges();
        }

                public T Save<T>(T entity)
                {
                        _session.SaveOrUpdate(entity);
                        return entity;
                }

                public T Insert<T>(T entity)
                {
                        _session.Save(entity);
                        return entity;
                }

                public void SubmitChanges()
                {
                        try
                        {
                                _session.Transaction.Commit();
                                _session.BeginTransaction();
                        }
                        catch
                        {
                                _session.Transaction.Rollback();
                                throw;
                        }
                }

                public void Delete<T>(T entity) where T : Core.Domain.Interfaces.IEntity
                {
                        if (entity != null)
                                _session.Delete(entity);
                }


    }

public class DatabaseEngine
    {
    }


public class SqlServer : DatabaseEngine { }

public abstract class Informix : DatabaseEngine
    {
    }
  public abstract class DB2 : DatabaseEngine { }


public class InformixRegistry : Registry
    {
       public InformixRegistry()
       {
           string informix = typeof(Informix).ToString();
           For<IRepository<Informix>>().Use<Repository<Informix>>();
           For<ISessionFactory>().Singleton()
               .Use(() => new NHibernateHelper().BuildInformixSessionFactory()).Named(informix);
           For<ISession>().HybridHttpOrThreadLocalScoped()
               .Use(ctx =>
               {
                   try {
                       var session = ctx.GetInstance<ISessionFactory>(informix).OpenSession();
                       session.FlushMode = FlushMode.Commit;
                       session.BeginTransaction();
                       return session;
                   }
                   catch
                   {
                       return null;
                   }
               }).Named(informix);
       }

public class SqlServerRegistry : Registry
       {
              public SqlServerRegistry()
              {
                     string sql = typeof(SqlServer).ToString();
                     For<IRepository<SqlServer>>().Use<Repository<SqlServer>>();
                     For<ISessionFactory>().Singleton()
                           .Use(() => new NHibernateHelper().BuildSqlServerSessionFactory()).Named(sql);
                     For<ISession>().HybridHttpOrThreadLocalScoped()
                           .Use(ctx =>
                           {
                                  var session = ctx.GetInstance<ISessionFactory>(sql).OpenSession();
                                  session.FlushMode = FlushMode.Commit;
                                  session.BeginTransaction();
                                  return session;
                           }).Named(sql);
              }
       }


public static class BootStrapper
       {
              public static void RegisterIoC()
              {
                     ObjectFactory.Initialize(x =>
                     {
                           x.For<HttpContextBase>().Use(() => new HttpContextWrapper(HttpContext.Current));
                x.For<IEnvironment>().Use<CstmEnvironmentDecorator>();
                           x.Scan(y =>
                            {
                                  y.TheCallingAssembly();
                                  y.LookForRegistries();
                           });
                x.For<IRepository>().Use<Repository<SqlServer>>();
                     });
              }

              public static void RegisterIoCControllerFactory()
              {
                     ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
              }
       }
For MVC
public class StructureMapControllerFactory : DefaultControllerFactory
       {
              protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
              {
            if (controllerType != null)
            {
                return (IController)ObjectFactory.GetInstance(controllerType);
            }
            return null;
              }
       }



So above method tells, there is two way of creating named instance of repository . either you create this as registry and named it and store it in objectfactory.structuremap. else
On runtime create the named session of repository.

You are registering all instance of repository either through Registry or by you code that you wrote in wcf. (creating indivuisal session factory for all connections without defining registry to return named instance of repository )

Refer to my previous post on how we can dynamically create different instance of repository in structure map.

No comments:

Post a Comment