MongoDB con Norm

Últimamente se ha puesto de moda las bases de datos NoSql y realmente es una buena alternativa si no necesitas una base de datos relacional y es mucho más potente que utilizar por ejemplo un fichero XML.

 MongoDB es una base de datos documental no existe el concepto de tabla, solo contamos con colecciones de objetos en formato JSon y de código abierto. Una solución escalable y de alto rendimiento que nos permite trabajar con índices, replicación y alta disponibilidad. MongoDB está realizado en C++ pero su cliente soporta múltiples Drivers de lenguajes de programación, tanto por mongodb.org como por la comunidad de desarrolladores. Para .Net tiene drivers para C# y F#.

Para mis ejemplo utilizaré Norm un driver para C# que facilita la interacción con las colecciones, la serialización/deserialización de objetos JSOn como documentos “BSON” a tipos .NET y la utilización de LinQ-To-Mongo. Otra de las utilidades que he utilizado es mongoVUE para administrar nuestras bases de datos de una forma gráfica.

 

Con esta utilidad podéis ver los datos en formato árbol o en JSon.

 

 

La Instalación

La instalación es muy simple:

  1. Crear los directorios “C:MongoDBdata” y “C:MongoDBlogs”
  2. Copiar los ficheros de la instalación MongoDB
  3. En el directorio “C:MongoDBbin” ejecutar: “mongod –dbpath C:MongoDBdata –directoryperdb –install –logpath C:MongoDBlogslog.txt” “En Windows 7, ejecutar el CMD como administrador para no tener problemas”
  4. Arrancar el servicio de MongoDB

El Modelo

Una de las ventajas de Norm es que podemos utilizar nuestras entidades sin necesidad de realizar grandes cambios, el único requerimiento es utilizar el objeto ObjectId para que MongoDb lo utilice como identificador de los registros.

 [DataContract]
    public class Persona
    {
        public ObjectId Id { get; set; }
        [DataMember]
        public string Nombre { get; set; }
        [DataMember]
        public string Apellidos { get; set; }
        [DataMember]
        public DateTime Fecha { get; set; }
        [DataMember]
        public string Poblacion { get; set; }
        [DataMember]
        public int Hermanos { get; set; }
        [DataMember]
        public List Aficiones { get; set; }

    }
    [DataContract]
    public class Aficion
    {
         [DataMember]
        public string Nombre { get; set; }
         [DataMember]
        public string Descripcion { get; set; }
    }

La Conexión

Para conectar con nuestra base de datos tenemos que especificar el nombre de la base de datos, el servidor el puerto y un string con las opciones.

private Mongo mongo;
public RepositoyNomgoDB()
{
   mongo = new Mongo("EjMongoDB", "localhost", "27017", string.Empty);
}

Las Consultas

Para todas nuestras consultas podemos utilizar objetos anónimos o consultas LinQ. Lo primero que tenemos que hacer e obtener la colección que queremos utilizar, como si fuera una tabla de una base de datos relacional.

var collection = (MongoCollection)mongo<Personas>.GetCollection("Personas");

Una vez que tenemos la colección podemos utilizar las típicas sentencias CRUD.

 collection.Insert(persona);
 collection.Delete(persona);
 collection.Save(persona);
 collection.UpdateOne(persona.Id, persona);

Ahora ya podemos realizar nuestras consultas utilizando la forma que nos sea más cómoda;

Buscar un Resultado:

//NoRM anonymous objects:
var persona = mongo.GetCollection<Personas>("Personas")
                             .FindOne(new { Nombre = "Marc" });
//NoRM Linq:
var personalinQ = mongo.GetCollection<Personas>("Personas")
                                                 .AsQueryable()
                                  .Where(per => per.Nombre == "Marc"
                                && per.Apellidos == "Rubiño").ToList();

Buscar Varios Resultados o paginar los resultados:

//NoRM anonymous objects:
var persona = mongo.GetCollection<Personas>("Personas").Find(new { },
                                new { Fecha = OrderBy.Descending }, 2, 1)
                                 .ToList();
//NoRM Linq:
var persona = mongo.GetCollection<Personas>("Personas").AsQueryable()
                                 .OrderByDescending(per => per.Fecha)
                                  .Skip(1)
                                  .Take(2).ToList();

Operadores Condicionales:

 //Mayor que
var persona = mongo.GetCollection<Personas>("Personas").AsQueryable()
                            .Where(per => per.Hermanos > 3).ToList();
//Igual o Mayor
var persona = mongo.GetCollection<Personas>("Personas").AsQueryable()
                             .Where(per => per.Hermanos >= 3).ToList();
//Diferente
var persona = mongo.GetCollection<Personas>("Personas").AsQueryable()
                              .Where(per => per.Hermanos != 3).ToList();
//En
var persona = mongo.GetCollection<Personas>("Personas").Find(
                   new { Aficiones = Q.In("Futbol", "Música") }).ToList();
//NO En
var persona = mongo.GetCollection<Personas>("Personas").Find(
             new { Aficiones = Q.NotIn("Futbol", "Música") }).ToList();
//Existe
var persona = mongo.GetCollection<Personas>("Personas").Find(
                           new { Apellidos = Q.Exists(true) }).ToList();
//OR
var persona = mongo.GetCollection<Personas>("Personas")
                             .Find(Q.Or(new { Nombre = "Marc" },
                             new { Aficiones = "Futbol" })).ToList();

Distinto y Count:

//Count
 var persona = mongo.GetCollection<Personas>("Personas")
                        .Count(new { Poblacion = "Cambrils" });
//Distinct
var persona = mongo.GetCollection<Personas>("Personas")
                                 .Distinct("Aficiones");

Con expresiones Regulares:

//Empieza por Ma
 var persona = mongo.GetCollection<Personas>("Personas").AsQueryable()
                         .Where(per => Regex.IsMatch(per.Nombre, "^Ma"))
                          .ToList();

Ya podemos añadir y obtener los registros desde nuestra base de datos NoSql de Personas

 

Espero que en la próxima entrega pueda hacer un ejemplo más específico para una aplicación ASP.NET.

CrossPosting: http://mrubino.net 

 

 

 

Perfiles de Usuarios ASP.NET & MVC

Una de las dudas más habituales en los foros de ASP.NET, es como mantener una variable disponible para un usuario. Lo primero que se nos puede pasar por la cabeza es utilizar la sesión para guardar esta información, pero desde ASP.NET 2.0 tenemos otras alternativas más adecuadas para estas cosas y además nos puede servir tanto para usuarios anónimos, como para usuarios autentificados.

  ¡¡ No tenemos que utilizar la sesión para todo !!!  y tanto nos sirve para ASP.NET como para ASP.NET MVC 

Usuarios autentificados.

Una vez el usuario se ha autentificado, se asocia el perfil a la identidad del usuario en el contexto actual system.web.httpcontext.user 

Usuarios anónimos

El perfil para los usuarios anónimos no está habilitada de forma predeterminada y hay que especificarlo de forma explícita.

Para poder tener estas propiedades del perfil habilitadas para los usuarios anónimos ASP.NET crea una cookie donde se establece una identidad única para el usuario y poderlo identificar cada vez que el usuario acceda a la página web. Esta cookie tiene una caducidad de 70 días y se renueva automáticamente cuando el usuario accede al sitio.

Si necesitamos controlar cuando un usuario pasa de ser anónimo a usuario autentificado, podemos controlar este paso en el momento que el usuario se autentifica y se lanza el evento MigrateAnonymous incluido en el fichero Global.asax.

Tipos Soportados

Si no se especifica el tipo del dato que queremos mantener, por defecto esta propiedad se guardara como string, pero podemos guardar tipos escalares (texto, números, fechas) tan solo especificando el tipo en la configuración de la propiedad.

image

Para trabajar con tipos complejos o propios tenemos que especificar el tipo de serialización que queremos utilizar.

Nos tenemos que acordar de marcar nuestras clases como serializables para no tener problemas al guardar los datos.

namespace Demo.Profile
{
    [System.Serializable]
    public class Persona
    {
        public string Nombre { get; set; }
        public int Edad { get; set; }
        public DateTime Cumple { get; set; }
    }
}

Y cuando especificamos el tipo en el fichero de configuración no nos tenemos que olvidar el namespace.

image

Proveedores

Otra de las ventajas para utilizar los perfiles de usuario es que se basan en los famosos proveedores de ASP.NET y podemos definir donde guardar esta información, en base de datos, un fichero xml, etc.

1000_18_249_Aa478948_asp2prvdr0101en-usMSDN_10

Para este ejemplo he utilizado la tabla de sqlExpres que viene por defecto con nuestras aplicaciones ASP.NET.

TablasProfile

Utilizar los Perfiles de Usuario

Una vez que tenemos todo configurado ya podemos comenzar a utilizar los perfiles según nuestras necesidades.

Lo primero que podemos necesitar es actuar dependiendo si el usuario actual es un usuario anónimo o es un usuario autentificado “Profile.IsAnonymous” y establecer el valor de las variables que tenemos configurado en el perfil, finalmente nos tenemos que acordar de guardar la modificaciones y listos.

Guardamos tipos escalares:

GuradarProfile

Guardamos tipos complejos:

PersonaProfile

Luego dispondremos de esta información para toda la aplicación y para este usuario.

RecuperarProfile

Con esto lo tenemos todo de una manera fácil y persistente. Recordar que NO todas las aplicaciones ASP.NET viven de las sesiones y desde ASP.NET2.0 disponemos de esta alternativa que podemos utilizar incluso con las aplicaciones MVC.

CrossPosting: http://mrubino.net/