jueves, 17 de septiembre de 2015

NHibernateManagerSql.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate.Cfg;
using NHibernate;
using FluentNHibernate.Cfg;

namespace Migration.Target.Dao.UnitOfWork
{
    public sealed class NHibernateManagerSql
    {
        internal sealed class NHibernateSettings
        {
            public Type DbContextType { get; private set; }
            public string ConfigFileName { get; private set; }
            public Configuration Configuration { get; private set; }
            public ISessionFactory SessionFactory { get; private set; }

            internal NHibernateSettings(Type dbContextType, string configFileName, Configuration configuration, ISessionFactory sessionFactory)
            {
                this.DbContextType = dbContextType;
                this.ConfigFileName = configFileName;
                this.Configuration = configuration;
                this.SessionFactory = sessionFactory;
            }
        }

        #region Singleton

        private static readonly object sync = new object();

        private static NHibernateManagerSql _instance;
        public static NHibernateManagerSql Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (sync)
                    {
                        if (_instance == null)
                            _instance = new NHibernateManagerSql();
                    }
                }
                return _instance;
            }
        }

        #endregion


        private IList<NHibernateSettings> _dbs;

        private NHibernateManagerSql()
            : base()
        {
            this._dbs = new List<NHibernateSettings>();
        }

        internal ISession GetNewSession(Type dbUnitType, string configFileName, Action<FluentMappingsContainer> modelBuilder)
        {
            NHibernateSettings dbItem = this._dbs.FirstOrDefault(x => x.DbContextType == dbUnitType && x.ConfigFileName == configFileName);

            ISessionFactory sessionFactory;
            if (dbItem != null)
            {
                sessionFactory = dbItem.SessionFactory;
            }
            else
            {
                Configuration configuration = new Configuration();
                configuration.Configure(configFileName);

                FluentConfiguration fluentConfiguration = Fluently.Configure(configuration);
                fluentConfiguration.Mappings(m => modelBuilder(m.FluentMappings));
                sessionFactory = fluentConfiguration.BuildSessionFactory();

                this._dbs.Add(new NHibernateSettings(dbUnitType, configFileName, configuration, sessionFactory));
            }

            return sessionFactory.OpenSession();
        }

        internal Configuration GetConfiguration(Type dbUnitType, string configFileName)
        {
            NHibernateSettings dbItem = this._dbs.FirstOrDefault(x => x.DbContextType == dbUnitType && x.ConfigFileName == configFileName);

            return dbItem.Configuration;
        }
    }
}

NHibernateContextSql.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using FluentNHibernate.Cfg;
using NHibernate.Cfg;
using Migration.Target.Dao.UnitOfWork.Mappings;

namespace Migration.Target.Dao.UnitOfWork
{
    public class NHibernateContextSql : IDisposable
    {
        private string _configFileName;
        public string ConfigFileName { get { return this._configFileName; } }

        private ISession _session;
        public ISession Session { get { return this._session; } }

        public NHibernateContextSql(string configFileName)
        {
            this._configFileName = configFileName;
            this._session = NHibernateManagerSql.Instance.GetNewSession(this.GetType(), this._configFileName, this.OnModelCreating);
        }

        protected void OnModelCreating(FluentMappingsContainer modelBuilder)
        {
            modelBuilder
                .Add(typeof(EmpleadoMap))
                .Add(typeof(TrabajoMap))
                ;
        }

        public ITransaction BeginTransaction()
        {
            return this.Session.BeginTransaction();
        }

        public void Dispose()
        {
            if (this.Session.IsOpen)
                this.Session.Close();
            this.Session.Dispose();
        }



        #region Métodos estáticos exclusivos para crear y/o resolver instancias

        private static Func<NHibernateContextSql> _resolveInstance;

        public static void Configure(Func<NHibernateContextSql> resolveInstance)
        {
            _resolveInstance = resolveInstance;
        }

        public static NHibernateContextSql ResolveInstance()
        {
            if (_resolveInstance != null)
                return _resolveInstance.Invoke();
            return null;
        }

        #endregion



        #region Métodos estáticos exclusivos para instalar y/o configurar la base de datos

        public static void RunDbSetup(bool restore)
        {
            NHibernateContextSql dbContext = NHibernateContextSql.ResolveInstance();
            using (ITransaction trx = dbContext.BeginTransaction())
            {
                Configuration configuration = NHibernateManagerSql.Instance.GetConfiguration(dbContext.GetType(), dbContext.ConfigFileName);

                //if (restore)
                //{
                //    //Regenera el esquema, borra datos
                //    NHibernate.Tool.hbm2ddl.SchemaExport schemaExport
                //        = new NHibernate.Tool.hbm2ddl.SchemaExport(configuration);
                //    //schemaExport.Drop(true, true);
                //    //schemaExport.Create(true, true);
                //    using (FileStream fs = new FileStream(@"c:\Temp\MonitorDB.script", FileMode.Create, FileAccess.Write))
                //    using (StreamWriter sw = new StreamWriter(fs))
                //    {
                //        schemaExport.Create(sw, false);
                //    }
                //}
                //else
                //{
                //    //Comprueba esquema
                //    NHibernate.Tool.hbm2ddl.SchemaValidator schemaValidator
                //        = new NHibernate.Tool.hbm2ddl.SchemaValidator(configuration);
                //    schemaValidator.Validate();
                //}

                //Sincroniza enumeradores

                if (restore)
                {
                    //Crea datos desde cero
                    CreateInitialData();
                }

                //Salva todos los cambios
                trx.Commit();
            }
        }




        private static void CreateInitialData()
        {


        }

        #endregion
    }
}

Mapping.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FluentNHibernate.Mapping;
using Migration.Target.Dao.Entities;

namespace Migration.Target.Dao.UnitOfWork.Mappings
{
    internal abstract class Mapping<TEntity> : ClassMap<TEntity>
        where TEntity : Entity
    {
        public Mapping()
            : base()
        {
            this.LazyLoad();
        }
    }
}

Repository.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Migration.Target.Dao.Entities;
using Migration.Target.Dao.UnitOfWork;
using NHibernate;
using NHibernate.Linq;

namespace Migration.Target.Dao.Repositories
{
    public class Repository<TEntity>
        where TEntity : Entity
    {
        protected NHibernateContextSql GetDbContext()
        {
            NHibernateContextSql dbContext = NHibernateContextSql.ResolveInstance();
            return dbContext;
        }


        #region Miembros de IEntityRepository<TEntity>

        public TEntity Get(long id)
        {
            NHibernateContextSql dbContext = this.GetDbContext();
            ISession session = dbContext.Session;
            return session.Get<TEntity>(id);
        }


        public IQueryable<TEntity> GetQuery()
        {
            NHibernateContextSql dbContext = this.GetDbContext();
            ISession session = dbContext.Session;
            IQueryable<TEntity> queryBase = session.Query<TEntity>();
            return queryBase;
        }

        public TEntity Create(TEntity entity)
        {
            NHibernateContextSql dbContext = this.GetDbContext();
            ISession session = dbContext.Session;
            entity = session.Save(entity) as TEntity;
            return entity;
        }

        public TEntity Update(TEntity entity)
        {
            NHibernateContextSql dbContext = this.GetDbContext();
            ISession session = dbContext.Session;
            session.Update(entity);
            return entity;
        }

        public TEntity Delete(TEntity entity)
        {
            NHibernateContextSql dbContext = this.GetDbContext();
            ISession session = dbContext.Session;
            session.Delete(entity);
            return entity;
        }

        #endregion
    }
}

EntidadFilter.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Migration.Target.Dao.Entities;

namespace Migration.Target.Dao.Filters
{
    public class EntidadFilter:Filter<Entidad>
    {
        public override IQueryable<Entidad> BuildFilter(IQueryable<Entidad> queryBase)
        {
            return queryBase;
        }
    }
}

Sort.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Migration.Target.Dao.Entities;
using System.Linq.Expressions;
using System.ComponentModel;

namespace Migration.Target.Dao.Filters
{
    public sealed class Sort<TEntity>
        where TEntity : Entity
    {
        private class SortField
        {
            public LambdaExpression Property { get; set; }
            public ListSortDirection Direction { get; set; }
        }

        private Queue<SortField> Fields { get; set; }

        internal Sort()
            : base()
        {
            this.Fields = new Queue<SortField>();
        }

        internal IQueryable<TEntity> BuildSortBy(IQueryable<TEntity> query)
        {
            bool flag = false;

            while (this.Fields.Any())
            {
                string method = string.Empty;
                SortField order = this.Fields.Dequeue();
                if (flag == false)
                {
                    if (order.Direction == ListSortDirection.Ascending)
                        method = "OrderBy";
                    else
                        method = "OrderByDescending";
                }
                else
                {
                    if (order.Direction == ListSortDirection.Ascending)
                        method = "ThenBy";
                    else
                        method = "ThenByDescending";
                }
                flag = true;

                MethodCallExpression methodCallExpression
                    = Expression.Call(
                        typeof(Queryable),
                        method,
                        new Type[] { query.ElementType, order.Property.Body.Type },
                        new[] { query.Expression, Expression.Quote(order.Property) }
                    );

                query = query.Provider.CreateQuery<TEntity>(methodCallExpression);
            }

            return query;
        }

        private void InternalAddSort(LambdaExpression expression, ListSortDirection direction)
        {
            this.Fields.Enqueue(new SortField() { Property = expression, Direction = direction });
        }

        public void AddSort<TValue>(Expression<Func<TEntity, TValue>> expression, ListSortDirection direction)
        {
            this.InternalAddSort(expression, direction);
        }

        public void AddSort(string field, ListSortDirection direction)
        {
            ParameterExpression ent = Expression.Parameter(typeof(TEntity));

            Expression par = ent;
            Expression bod = null;
            foreach (string sec in field.Split('.'))
            {
                bod = Expression.MakeMemberAccess(par, par.Type.GetMember(sec)[0]);
                par = bod;
            }

            LambdaExpression lam = Expression.Lambda(bod, ent);
            this.InternalAddSort(lam, direction);
        }
    }
}

Pager.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Migration.Target.Dao.Entities;

namespace Migration.Target.Dao.Filters
{
    public sealed class Pager<TEntity>
        where TEntity : Entity
    {
        public int CurrentPage { get; set; }
        public int RowsPerPage { get; set; }
        public int TotalPages { get; private set; }
        public int TotalRows { get; private set; }

        internal Pager()
            : base()
        {
            this.CurrentPage = 0;
            this.RowsPerPage = 0;
        }

        internal IQueryable<TEntity> BuildPager(IQueryable<TEntity> query)
        {
            this.TotalRows = 0;
            this.TotalPages = 0;

            IQueryable<TEntity> paginatedQuery = query;

            bool paginated = (this.RowsPerPage > 0 && this.CurrentPage > 0);
            if (paginated)
            {
                this.TotalRows = query.Count();

                //Dado que hay problemas con el soporte de paginado para Access, me veo en la obligacion de adaptar el filtro
                int minResults = (this.CurrentPage - 1) * this.RowsPerPage;
                int maxResults = (this.CurrentPage * this.RowsPerPage);
                var resultRows = query.Take(maxResults).Select(x => x.Id).ToList();

                resultRows.RemoveRange(0, resultRows.Count < minResults ? resultRows.Count : minResults);
                if (resultRows.Count > 0)
                    query = query.Where(x => resultRows.Contains(x.Id));


                decimal estimatedPages = (decimal)this.TotalRows / (decimal)this.RowsPerPage;
                int roundPage = (int)Math.Truncate(estimatedPages);
                int extraPage = (this.TotalRows % this.RowsPerPage > 0) ? 1 : 0;
                this.TotalPages = roundPage + extraPage;


                paginatedQuery = query/*.Skip((this.CurrentPage - 1) * this.RowsPerPage)*/.Take(this.RowsPerPage);
            }

            return paginatedQuery;
        }
    }
}

Filter.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Migration.Target.Dao.Entities;

namespace Migration.Target.Dao.Filters
{
    public abstract class Filter<TEntity>
       where TEntity : Entity
    {
        public Sort<TEntity> Sort { get; set; }
        public Pager<TEntity> Pager { get; set; }

        public Filter()
        {
            this.Sort = new Sort<TEntity>();
            this.Pager = new Pager<TEntity>();
        }

        public abstract IQueryable<TEntity> BuildFilter(IQueryable<TEntity> queryBase);
    }
}

Entidad.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Migration.Target.Dao.Entities
{
    public class Entidad:Entity
    {      
        public virtual string   Nombre              { get; set; }
        public virtual string   Apellido            { get; set; }
        public virtual string   Email               { get; set; }
        public virtual string   Telefono            { get; set; }
        public virtual DateTime Fecha_nacimiento    { get; set; }
        public virtual Trabajo  Trabajo          { get; set; }
        public virtual double   Salario             { get; set; }
        public virtual double   Comision_id         { get; set; }
        public virtual long     Jefe_id             { get; set; }
        public virtual long     Departamento_id     { get; set; }

    }
}

Entity.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Migration.Target.Dao.Entities
{
    public abstract class Entity
    {
        public virtual long Id { get; set; }
    }
}

EntidadBusiness.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Migration.Target.Dao.Entities;

namespace Migration.Target.Business
{
    public class EntidadBusiness:Business<Entidad>
    {
    }
}

BusinessProviderSql.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Migration.Target.Business
{
    public static class BusinessProviderSql
    {
        private static  EmpleadoBusiness _empleadoBusiness;
        public static EmpleadoBusiness GetEmpleadoBusiness()
        {
            if (_empleadoBusiness == null)
                _empleadoBusiness = new EmpleadoBusiness();
            return _empleadoBusiness;
        }
    }
}

Business.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Migration.Target.Dao.Entities;
using Migration.Target.Dao.Repositories;
using Migration.Target.Dao.Filters;

namespace Migration.Target.Business
{
    public abstract class Business<TEntity>
    where TEntity : Entity
    {
        private Repository<TEntity> _repository;
        protected Repository<TEntity> GetRepository()
        {
            if (this._repository == null)
                this._repository = Activator.CreateInstance<Repository<TEntity>>();
            return this._repository;
        }

        #region Miembros de IEntityService<TEntity>

        public TEntity Get(long id)
        {
            Repository<TEntity> repository = this.GetRepository();

            TEntity entity = repository.Get(id);
            if (entity == null)
                throw new Exception("No existe el registro");

            return entity;
        }

        protected virtual IQueryable<TEntity> FilteringRules(IQueryable<TEntity> queryBase)
        {
            return queryBase;
        }

        public IList<TEntity> List()
        {
            Repository<TEntity> repository = this.GetRepository();

            IQueryable<TEntity> queryBase = repository.GetQuery();
            queryBase = this.FilteringRules(queryBase);

            return queryBase.ToList();
        }

        public IList<TEntity> Find(Filter<TEntity> filter)
        {
            if (filter == null)
                throw new ArgumentNullException("filter");

            Repository<TEntity> repository = this.GetRepository();

            IQueryable<TEntity> queryBase = repository.GetQuery();

            //Prepara query con el filtro
            queryBase = filter.BuildFilter(queryBase);
            //Incluye reglas de filtrado
            queryBase = this.FilteringRules(queryBase);
            //Prepara ordenamiendo
            queryBase = filter.Sort.BuildSortBy(queryBase);
            //Prepara paginado
            queryBase = filter.Pager.BuildPager(queryBase);

            return queryBase.ToList();
        }

        public TEntity First(Filter<TEntity> filter)
        {
            if (filter == null)
                throw new ArgumentNullException("filter");

            Repository<TEntity> repository = this.GetRepository();

            IQueryable<TEntity> queryBase = repository.GetQuery();

            //Prepara query con el filtro
            queryBase = filter.BuildFilter(queryBase);
            //Incluye reglas de filtrado
            queryBase = this.FilteringRules(queryBase);
            //Prepara ordenamiendo
            queryBase = filter.Sort.BuildSortBy(queryBase);

            // TODO: Revisar
            return queryBase.FirstOrDefault();
        }

        public TEntity Single(Filter<TEntity> filter)
        {
            if (filter == null)
                throw new ArgumentNullException("filter");

            Repository<TEntity> repository = this.GetRepository();

            IQueryable<TEntity> queryBase = repository.GetQuery();

            //Prepara query con el filtro
            queryBase = filter.BuildFilter(queryBase);
            //Incluye reglas de filtrado
            queryBase = this.FilteringRules(queryBase);

            // TODO: Revisar
            return queryBase.SingleOrDefault();
        }

        public int Count(Filter<TEntity> filter)
        {
            if (filter == null)
                throw new ArgumentNullException("filter");

            Repository<TEntity> repository = this.GetRepository();

            IQueryable<TEntity> queryBase = repository.GetQuery();

            //Prepara query con el filtro
            queryBase = filter.BuildFilter(queryBase);
            //Incluye reglas de filtrado
            queryBase = this.FilteringRules(queryBase);

            // TODO: Revisar
            return queryBase.Count();
        }

        public virtual TEntity Create(TEntity entity)
        {
            Repository<TEntity> repository = this.GetRepository();
            TEntity entityReal = repository.Create(entity);
            return entity;
        }

        public virtual TEntity Update(TEntity entity)
        {
            Repository<TEntity> repository = this.GetRepository();
            TEntity entityReal = repository.Update(entity);
            return entity;
        }

        public virtual TEntity Delete(TEntity entity)
        {
            Repository<TEntity> repository = this.GetRepository();
            TEntity entityReal = repository.Delete(entity);
            return entity;
        }

        #endregion
    }
}

Estructura de una proyecto


NHybernateOrcl.config

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">

  <session-factory>

    <property name = "connection.connection_string_name">DBOrcl</property>
    <property name = "dialect">NHibernate.Dialect.Oracle10gDialect</property>
    <property name = "connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
    <property name = "connection.driver_class">NHibernate.Driver.OracleClientDriver</property>
    <property name = "hbm2ddl.keywords">auto-quote</property>
    <property name = "show_sql">true</property>
    <property name = "connection.release_mode">auto</property>
    <property name = "adonet.batch_size">500</property>
    <property name ="connection.connection_string">
      User Id=HR;
      Password=HR;
      Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=
      (PROTOCOL=TCP)(HOST=192.168.56.105)(PORT=1521)))
      (CONNECT_DATA=(SERVICE_NAME=orcl)));
      Pooling=true;
      Enlist=false;


    </property>



    <!--<property name=""></property> -->

  </session-factory>
</hibernate-configuration>

martes, 1 de septiembre de 2015

NHibernateSql.config

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory>

    <property name="connection.connection_string_name">DBSql</property>
    <property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>
    <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
    <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
    <property name="hbm2ddl.keywords">auto-quote</property>
    <property name="show_sql">true</property>
    <property name="connection.release_mode">auto</property>
    <property name="adonet.batch_size">500</property>
    <!--<property name="cache.provider_class">NHibernate.Caches.SysCache.SysCacheProvider, NHibernate.Caches.SysCache</property>
    <property name="cache.use_second_level_cache">true</property>-->

    <!-- Mapping assemblies -->
    <!-- Can't map it for Fluent NHibernate here; instead, load the mapping assembly in Global.asax.cs.
      If you're still using HBMs, you can use the mapping here or pass the assembly via Global.asax.cs
      as well, just like you can do with the Fluent NHibernate assembly(s). -->

  </session-factory>
</hibernate-configuration>