30/12/08

Ranking de la Universidades 2008

Revisando la columna de Aldo Mariátegui , Alditus nos comentaba que en ranking de las 500 Mejores Universidades de este año 2008 , que se nos va, NO SE ENCUENTRA ninguna universidad Peruano , Ni Publica , Ni Privada, Ni Católica, Adventista ó cualquiera, pero sin embargo , encontré 6 Brasileras y hasta 2 Chilenas, se siente un poco de pica por eso, pero en realidad tampoco es para extrañarse; Ahora yo me pregunto en que puestos estarán las fichas universidades limeñas como la U de Lima , UPC , USIL y hasta se cola por ahí la U de Piura del Opus??? seria bueno averiguarlo,También me pregunto en que puesto estará mi querida Alma Mater , La Universidad Nacional de Trujillo.

Lo que si queda claro es que ninguna universidad Peruana que se jacte de ser la mejor , por lo menos entre las 500 mejores del mundo no está.

Descárgate el PDF con el ranking Aquí

Bueno , esperemos que algún día este alguna Universidad Peruana siquiera entre las 500 mejores del mundo.

Nos Vemos, Muchas Gracias.

José Fabricio Rojas

05/12/08

NHibernate 2.0 + NHHelper sobre ASP.NET

Hola,
Despues de mucho tiempo de ausencia , empezaré a publicar una serie de post sobre Nhibernate sobre aplicaciones web, iremos desarrollando una aplicación de manera evolutiva, desde una aplicación simple hasta una aplicación basada en N-capas.
Lo primero para esta demo utilizaremos:
- SQL Server Express 2005
- NHibernate 2.0, si aún no lo descargas , descárgatelo de aqui
- ASP.NET 2.x
1. Crearemos una aplicación web con ayuda del visual studio 2005.
 image
2. Distribuiremos nuestra aplicación en las carpetas:
- Entities, nuestra carpetas de entidades.

- Lib, Librerias de Nhibernate y las demás que utiliza.

- Mappings, Archivos de mapeo (hbm.xml).

- Archivo de configuración de Nhibernate (hibernate.cfg.xml)

3. Esta aplicación es un mantenimiento básico de un Login, en donde tenemos 3 tablas, Users, Roles, UserRole.

image

4. Nuestro Diagrama de clases muestra las clases:

User: Que mapea la tabla Users

Role: Que mapea la tabla Roles

Estas se relaciónan mediante "Asociación" atravez de la entidad UserRole,

que el modelo de datos actua como una tabla intermedia(esto para romper

la relación de muchos a muchos, existente entre Users y Roles).

image 

5. La entidad Role:

using System;
using System.Collections.Generic;
namespace nhweb
{
    public class Role : IEquatable<Role>
    {
        private int idRole;
        private string role;
        private IList<UserRole> userroleList = new List<UserRole>();

        public virtual  int IdRole
        {
            get { return idRole; }
            set { idRole = value; }
        }

        public virtual  string RoleName
        {
            get { return role; }
            set { role = value; }
        }

        public virtual IList<UserRole> UserRoleList
        {
            get { return userroleList; }
            set { userroleList = value; }
        }

        #region Miembros de IEquatable<Role>

        public virtual bool Equals(Role other)
        {
            return other.IdRole.Equals(this.IdRole );
        }

        #endregion
    }
}

6. La Entidad User:

using System;
using System.Collections.Generic;
namespace nhweb
{
    public class User : IEquatable<User>
    {
        private int idUser;
        private string login;
        private string password;
        private IList<UserRole> userroleList = new List<UserRole>();

        public virtual int IdUser
        {
            get { return idUser; }
            set { idUser = value; }
        }

        public virtual string Login
        {
            get { return login; }
            set { login = value; }
        }

        public virtual string Password
        {
            get { return password; }
            set { password = value; }
        }

        public virtual IList<UserRole> UserRoleList
        {
            get { return userroleList; }
            set { userroleList = value; }
        }

        public virtual bool Equals(User obj)
        {
            return obj.Equals(this.IdUser);
        }
    }
}

7. La entidad UserRole:

using System;
namespace nhweb
{
    public class UserRole : IEquatable<UserRole>
    {
        private int idUserRole;
        private User objUser = new User();
        private Role objRole = new Role();

        public virtual int IdUserRole
        {
            get { return idUserRole; }
            set { idUserRole = value; }
        }
        public virtual User FkUser
        {
            get { return objUser; }
            set { objUser = value; }
        }
        public virtual Role FkRole
        {
            get { return objRole; }
            set { objRole = value;}
        }

        #region Miembros de IEquatable<UserRole>

        public virtual bool Equals(UserRole other)
        {
            if (other.IdUserRole.Equals(this.IdUserRole))
                return true;
            return false;
        }

        #endregion
    }
}

8. Los archivos de mapeo Role.hbm.xml, hay que recordar que estos deben
de estar como recursos incrustados.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="nhweb" namespace="nhweb">
  <class name="Role" table="Roles">
    <id name="IdRole" column="IdRole">
      <generator class="identity"></generator>
    </id>
    <property name="RoleName" column="Role" type="String"/>
    <bag name="UserRoleList" cascade="save-update" inverse="true">
      <key column="IdRole"/>
      <one-to-many class="UserRole"/>
    </bag>
  </class>
</hibernate-mapping>

9. Los Archivos de mapeo User.hbm.xml, hay que recordar que al igual que el
elemento anterior también debe de estar incrustado.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="nhweb" namespace="nhweb">
  <class name="User" table="Users">
    <id name="IdUser" column ="IdUser" type="int">
      <generator class="identity"/>
    </id>
    <property name="Login" type="String" not-null="true"/>
    <property name="Password" type="String" not-null="true"/>
    <bag name="UserRoleList" cascade="save-updat" inverse="true" lazy="true">
      <key column="IdUser"/>
      <one-to-many class="UserRole"/>
    </bag>
  </class>
</hibernate-mapping>

10. El Archivo de mapeo UserRole.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="nhweb" namespace="nhweb">
  <class name="UserRole" table="UserRole" lazy="true">
    <id name="IdUserRole">
      <generator class="identity"></generator>
    </id>
    <many-to-one name="FkUser" class="User" column="IdUser"/>
    <many-to-one name="FkRole" class="Role" column="IdRole"/>
  </class>
</hibernate-mapping>

11. El archivo de configuración de Nhibernate esta definido por:
- Driver
- Dialecto
- Cadena de Conección, entre los principales.*
image
*Hay que recordar que la propiedad "show_sql", indica que se mostrarán las consultas SQL que se generarán por Nhibernate, están consultas pueden ser visualizadas una vez configurado un framework de log, como Log4Net por ejm, la propiedad "current_session_context_class" indica que la aplicación tiene una configuración para web y que NH usa la sesion de ASP.NET(HttpContext) para mantener la sesion de NHibernate.

NHHelper

Esta clase abstracta es un Template ó plantila , esto quiere decir que en tiempo de ejecución adopta el tipo que se le indica.

Esta clase es la que realiza casi todo el trabajo, tanto con los metodos de acceso a datos y los de logica de negocio.

Si bien es cierto, es aun muy simple esta clase ,pues transaccionabilidad es solo a nivel de objeto, esto lo mejoraremos para la prox. versión , donde la transaccionalidad sera vital.( lo dejaré para una serie de post que publicaré en adelante)

por ejm nuestra clase seria:

using System;
using System.Collections.Generic;
using NHibernate.Type;
using NHibernate;
using NHibernate.Cfg;
namespace nhweb.Logic
{
    public abstract class NHHelper<T>
    {
        protected Configuration GetConfigurarion()
        {
            Configuration cfg = new Configuration();
            cfg.Configure("hibernate.cfg.xml");
            return cfg;
        }

        protected void Save(T entity)
        {

            ISessionFactory sessionFactory = GetConfigurarion().BuildSessionFactory();
            ISession session = sessionFactory.OpenSession();
            ITransaction transaction = null;
            try
            {
                transaction = session.BeginTransaction();
                session.Save(entity);
                transaction.Commit();
                session.Flush();
                session.Close();
            }
            catch (Exception )
            {
                if (transaction != null)
                    transaction.Rollback();
                throw;
            }
        }

        protected void Update(T entity)
        {
            ISessionFactory sesiones = GetConfigurarion().BuildSessionFactory();
            ISession sesion = sesiones.OpenSession();
            ITransaction transaccion = null;
            try
            {
                transaccion = sesion.BeginTransaction();
                sesion.SaveOrUpdate(entity);
                transaccion.Commit();
                sesion.Flush();
                sesion.Close();
            }
            catch (Exception )
            {
                if (transaccion != null) transaccion.Rollback();
                throw;
            }
        }

        protected void Delete(T entity)
        {
            ISessionFactory sesiones = GetConfigurarion().BuildSessionFactory();
            ISession sesion = sesiones.OpenSession();
            ITransaction transaccion = null;
            try
            {
                transaccion = sesion.BeginTransaction();
                sesion.Delete(entity);
                transaccion.Commit();
                sesion.Flush();
                sesion.Close();
            }

            catch (Exception )
            {
                if (transaccion != null) transaccion.Rollback();
                throw;
            }
        }

        protected void Delete(string myQuery, string[] parameters, object[] values)
        {
            ISessionFactory sesiones = GetConfigurarion().BuildSessionFactory();
            ISession sesion = sesiones.OpenSession();
            ITransaction transaccion = null;
            try
            {

                transaccion = sesion.BeginTransaction();
                IQuery consulta = sesion.CreateQuery(myQuery);
                for (int i = 0; i < parameters.Length; i++)
                {
                    consulta.SetParameter(parameters[i], values[i]);
                }
                sesion.Delete(consulta);
                transaccion.Commit();
                sesion.Flush();
                sesion.Close();
            }

            catch (Exception )
            {
                if (transaccion != null) transaccion.Rollback();
                throw;
            }
        }

        protected void Delete(string myQuery, object[] values, IType[] myType)
        {
            ISessionFactory sesiones = GetConfigurarion().BuildSessionFactory();
            ISession sesion = sesiones.OpenSession();
            ITransaction transaccion = null;
            try
            {

                transaccion = sesion.BeginTransaction();
                sesion.Delete(myQuery, values, myType);
                transaccion.Commit();
                sesion.Flush();
                sesion.Close();
            }

            catch (Exception )
            {
                if (transaccion != null) transaccion.Rollback();
                throw;
            }
        }

        protected IList<T> List()
        {
            List<T> orders = new List<T>();
            ISessionFactory sesiones = GetConfigurarion().BuildSessionFactory();
            ISession session = sesiones.OpenSession();
            ICriteria criteria = session.CreateCriteria(typeof(T));
            criteria.List(orders);
            return orders;
        }

        protected IList<T> List(string myQuery, string[] parameters, object[] values)
        {
            List<T> orders = new List<T>();
            ISessionFactory sesiones = GetConfigurarion().BuildSessionFactory();
            ISession session = sesiones.OpenSession();
            IQuery consulta = session.CreateQuery(myQuery);
            for (int i = 0; i < parameters.Length; i++)
            {
                consulta.SetParameter(parameters[i], values[i]);
            }
            consulta.List(orders);
            return orders;
        }
    }
}

La clase NHHelper, posee en primera instancia los metodos denominados CRUD, Create, Read, Update and Delete, Ademas de estos metodos tambien están los metodos de Listado (List), Listado por una consula, donde se pasan por parametos , la consulta HQL, en nombre de los parametros y su valor; Tambien un método de eliminación por una consulta HQL.

image

UserLogic

En esta demo , al no tener una capa de acceso de datos , ni una clase de Logica de negocios , por ser un ejemplo pequeño, todo el CRUD y principales funciones de negocios las implementaremos en esta clase.
Ahora,esta clase lo que hace es heredad de la clase abstract NHHelper y pasarle como tipo "User".
Los métodos "GetUserById", realiza una búsqueda con HQL atravéz del "Id" del Usuario, pasando como parámetros IdUser, La consulta HQL es en modo Texto y la asignación del parámetro se hace atravéz del operador ":".

Es muy impornate aqui el papel que juegan los Generics y Templates.

using System.Collections.Generic;
namespace nhweb.Logic
{
    public class UserLogic : NHHelper<User>
    {
        public void InsertUser(User user)
        {
            Save(user);
        }
        public void UpdateUser(User user)
        {
            Update(user);
        }
        public void DeleteUser(User user)
        {
            Delete(user);
        }
        public IList<User> ListUsers()
        {
            return List();
        }
        public User GetUserById(int IdUser)
        {
            string query = "from User u where u.IdUser=:IdUser";
            string[] paramString = new string[1];
            paramString[0] = "IdUser";
            object[] arrObject = new object[1];
            arrObject[0] = IdUser;
            return List(query, paramString, arrObject)[0];
        }
        public bool Validate(string Login,string Password)
        {
            string query = "from User u where u.Login=:Login and u.Password=:Password";
            string[] paramString = new string[2];
            paramString[0] = "Login";
            paramString[1] = "Password";
            object[] arrObject = new object[2];
            arrObject[0] = Login;
            arrObject[1] = Password;
            return List(query, paramString, arrObject).Count>0;
        }
        public User GetUser(User user)
        {
            if (Validate(user.Login,user.Password))
            {
                string query = "from User u where u.Login=:Login and u.Password=:Password";
                string[] paramString = new string[2];
                paramString[0] = "Login";
                paramString[1] = "Password";
                object[] arrObject = new object[2];
                arrObject[0] = user.Login;
                arrObject[1] = user.Password;
                return List(query, paramString, arrObject)[0];
            }
            else
            {
                return null;
            }
        }
    }
}


Nuestra presentación:
image

using System;
using nhweb.Logic;
using nhweb.Entities;
namespace nhweb
{
    public partial class _Default : System.Web.UI.Page
    {
        private readonly UserLogic userLog = new UserLogic();
        private User objUser = new User();
        protected  void btnLogin_Click(object sender, EventArgs e)
        {
            if (userLog.Validate(txtLogin.Text, txtPassword.Text))
            {
                objUser.Login = txtLogin.Text;
                objUser.Password = txtPassword.Text;
                User user = userLog.GetUser(objUser);
                Session.Add("id", user.IdUser);
                Response.Redirect("/frmMain.aspx?IdUser=" + user.IdUser);
            }

        }
    }
}

El código muestra la validación de un usuario, através de su login y contraseña, una vez pasada la validación obtenemos el usuario atravéz de los datos ingresados; y  enviamos por la url el Id de usuario logeado.

También tenemos un Master Page que contiene nuestras paginas ASPX.
Despues de la validación , enviado una vez el Id del Usuario por la URL , al cargar la página maestra, obtenemos el IdUser mediante el Metodo QueryString lo casteamos a un entero y recuperamos el Usuario a travéz de su id, de esta forma se tiene accedo a todas las propiedades del Usuario.

Tambien despues de esto , podria optar por guardar el Nombre de usuario en una variable de session, Aunque esto no es muy recomendable , pero para efectos de demo , lo haremos.

image 
 image

Ahora una Edición de un usuario (solo por efectos de demostración del campo mostraremos el password)

En el formulario de Inserción/edicion:

using System;
using nhweb.Entities;
using nhweb.Logic;

namespace nhweb
{
    public partial class frmEditUser : System.Web.UI.Page
    {
        private User objUser = new User();
        private UserLogic objLogUser = new UserLogic();
        protected void Page_Load(object sender, EventArgs e)
        {
            if(Request.QueryString["state"]=="edit")
            {
                objUser = objLogUser.GetUserById(Int32.Parse(Request.QueryString["IdUser"]));
                EditUser();
            }
        }

        protected void btnSave_Click(object sender, EventArgs e)
        {
            NewUser();
            if(Request.QueryString["state"]=="edit")
            {
                objLogUser.UpdateUser(objUser);
            }
            else
            {
                objLogUser.InsertUser(objUser);
            }
        }

        private void EditUser()
        {
            txtLogin.Text = objUser.Login;
        }

        private void NewUser()
        {
            objUser.Login = txtLogin.Text ;
            objUser.Password = txtPassword.Text;
        }
    }
}

Bueno, lo importante aquí es señalar el uso de la clase Helper(NHHelper) que al estilo de C++ , usa templates , con lo cual a puede optar el tipo que se le pase como parametro.

Espero les haya ayudado.
Saludos desde Lima , peru
Jose Fabricio Rojas