MvcScaffolding

En esta oportunidad quiero mostrarles la librería MvcScaffolding que me pareció por demás interesante y que trabaja en conjunto con Entity Framework y ASP.NET MVC 3. La finalidad principal de esta librería es facilitarnos tareas comunes y repetitivas de desarrollo que nos quitan tiempo y productividad.

Pero antes de comenzar vamos a ver que significa el termino Scaffold en nuestro ambito:

El termino Scaffolding es utilizado en muchas tecnologías de software para representar una forma rápida de generar un esquema básico de software que se puede editar y personalizar.

Con esta librería a partir de un modelo definido y escribiendo solo un par de comandos vamos a poder generar: la base de datos, los controladores con sus métodos de acción y sus respectivas vistas. Qué beneficios nos trae esto? que nos vamos a evitar tener que hacer esas tediosas acciones repetitivas como por ejemplo los formularios de carga y edición para las entidades más simples de nuestro proyecto.

Para comenzar lo primero que vamos hacer es crear un nuevo proyecto ASP.NET MVC 3 e instalar los paquetes Eyntity Framework y MvcScaffolding.

Para instalar ambas librerías podemos utilizar la consola que nos provee Nuget (en este post solo voy a mostrar como instalar el paquete MvcScaffolding, aunque la instalación de EF es similar). Para eso vamos a la opción “Tools\Library Package Manager\Package Manager Console” la cual nos abrirá la consola en una pestaña. Ahí escribimos el siguiente comando “Install-Package MvcScaffolding” y presionamos “Enter“:

Instalando MvcScafollding

Instalando MvcScafollding

Una vez que tenemos las librerías que vamos a utilizar instaladas vamos a definir el mismo modelo que en anteriores post y que estará compuesto por las entidades Agenda y Evento:

1:     public class Agenda
2:     {
3:         public int AgendaId { get ; set ; }
4:         public string Propietario { get ; set ; }
5:         public DateTime FechaCreacion { get ; set ; }
6:
7:         public virtual ICollection <Evento> Eventos { get ; set ; }
8:     }
1:     public class Evento
2:     {
3:         public int EventoId { get ; set ; }
4:         public int AgendaID { get ; set ; }
5:         public DateTime Fecha { get ; set ; }
6:         public string Comentario { get ; set ; }
7:
8:         public virtual Agenda Agenda { get ; set ; }
9:     }

Si seguiríamos con el procedimiento normal para armar nuestra aplicación, el siguiente paso seria escribir el controlador y las acciones que necesitamos para trabajar con nuestra Agenda y por último crear cada una de las vistas, cierto?… la idea de MvcScafollding es automatizar dicho proceso y simplemente escribiendo un par de lineas de comando generar nuestras interfaces CRUD (es decir, el listado de registros y los formularios de alta, baja, detalle y modificación de la entidad).

Vamos a abrir nuevamente la consola desde el menú “Tools\Library Package Manager\Package Manager Console” y escribimos el siguiente comando: “Scafolld Controller Agenda” (podemos observar que la última palabra del comando corresponde al nombre de la clase Agenda) y presionamos ENTER. Haremos lo mismo con la otra clase de nuestro modelo que es Evento.

Generando las interfaces UI y DB a partir del modelo

Generando las interfaces UI y DB a partir del modelo.

Podemos observar que entre otras cosas nos genero el controlador, las vistas y hasta el contexto de la base de datos automáticamente 🙂 :

Archivos generados

Archivos generados

Ejecutemos nuestra aplicación y accedamos a la vista de la Agenda (o a la de Eventos) para observar que ambos formularios están totalmente funcionales y persisten en la base de datos 🙂

Formulario de alta de una agenda

Formulario de alta de una agenda

Sin embargo, si vamos a la vista de eventos, el combo para seleccionar la agenda a la cual pertenece no se ve correctamente, esto debido a que en el modelo no se especifico que propiedad de la agenda queremos visualizar:

Error al visualizar el combo de Agendas

Error al visualizar el combo de Agendas

Para corregir esto simplemente agregamos el atributo DisplayColumn (provisto por la librería DataAnottations) a la clase Agenda pasandole como parámetro el atributo que deseamos que se visualice, en nuestro caso el Propietario de la misma:

1: [DisplayColumn ("Propietario")]
2: public class Agenda
3: {
4:     public int AgendaId { get ; set ; }
5:     public string Propietario { get ; set ; }
6:     public DateTime FechaCreacion { get ; set ; }
7:
8:     public virtual ICollection<Evento> Eventos { get ; set ; }
9: }

Volvemos a ejecutar y tenemos listo el formulario:

Combo de agendas mostrando el atributo que elegimos

Combo de agendas mostrando el atributo que elegimos

Una de las cosas que me llamo la atención de esta librería es forma en que arma los listados (o vistas index) ya que agregó una columna que nos permite saber el número de eventos que tiene cada agenda:

Listado de agendas

Listado de agendas

Con lo que respecta a la base de datos, la librería MvcScafollding esta integrada con Entity Framework y por default trabajan con base de datos SqlExpress. Un punto importante a saber es que el nombre con que se genera la base de datos coincide con el nombre completo del DbContext, en nuestro ejemplo el nombre de la DB es el siguiente MvcScaffolding.Models.MvcScaffoldingContext.

Otra de las cosas que me llamo la atención, es que no encontraba la cadena de conexión a la base de datos por ningun lado. Luego de leer un poco, me encontré con que, si no se especifica la cadena de conexión en el archivo web.config, EF lo que hará es generar “dinamicamente” la conexión a la base de datos utilizando el nombre del DbContext que estará corriendo sobre la instalacia local del SqlExpress (en mi caso .\SQLExpress). Recordemos que EF trabaja con el esquema de convenciones sobre el de configuraciones.

Cadena de conexión

Cadena de conexión

Pero bien podríamos modificarlo para que trabaje con SqlCE simplemente modificando la cadena de conexión dentro del archivo web.config como explicamos en este post.

Antes de finalizar el post, les voy a nombre algunas de las caracteristicas que ofrece MvcScaffolding:

  • Soporte para proyectos en C # como en VB.
  • Soporte para los ViewEngines Razor y ASPX.
  • Se pueden personalizar el código generado editando los templates T4.
  • Personalizar la lógica utilizada para generar las salidas modificando la lógica del PowerShell y de los templates T4.

Espero que les haya servido y que sigan investigando sobre esta librería que tiene muchísimo más para ofrecerles.

Anuncios

Run Web Camp 2011

Run Web Camp

Run Web Camp

El viernes 3 de junio tuve la suerte de poder asistir junto a mis compañeros.NET 🙂 al Run Web Camp que se realizo en la ciudad de San Francisco (Córdoba) organizado por la gente de Microsoft, del MUG (Microsoft User Group) y de la UTN.

El evento estuvo dividido en 4 charlas. La primera de ellas a cargo de Miguel Saez  que trato principalmente sobre IE9 y HTML5, pero ademas nos adelanto sobre las nuevas tecnologías que se vienen de acá en adelante por parte de MS. También nos comento acerca las diferentes plataformas que ofrece ASP.NET (Webforms, MVC y Webpages), el nuevo toolkit de desarrollo para Windows Phone llamado MANGO y las primeras impresiones de Windows 8 (del cual puedo decir que me pareció algo arriesgada la nueva interfaz basada en Metro, pero a su vez me pareció insteresante la estretegia de MS de querer tener un único SO corriendo sobre distintos dispositivos).

La segunda parte estuvo a cargo de Nicolas Bortolotti y fue acerca de ASP.NET MVC 3 y el View Engine Razor.

Finalmente las dos últimas charlas las dicto Carlos A. Perez y fueron acerca de Entity Framework y Windows Phone 7. Esta fueron por de mas interesantes, sobre todo por los conceptos teóricos del contenido dado y del gran conocimiento sobre las tecnologías en general que compartió con nosotros.

Para todos aquellos que tengan la oportunidad de asistir a este tipo de eventos, se los recomiendo!

Entity Framework 4.1 CF y Lazy Load

Para finalizar esta serie de post sobre Entity Framework 4.1 CF, vamos a hablar de una nueva caracteristica: soporte de Lazy Load (Carga Diferida).

Comencemos con una definición general de Lazy Load para que nos demos una mejor idea de que estamos hablando:

El Lazy Loading es un patron de diseño util y simple que se basa en ir cargando los distintos componentes de una clase cuando los vamos usando.

Ahora vamos a ver como trabaja este patrón de diseño dentro del framework EF CF 4.1.

En la definición anterior explica que Lazy Loading tiene como finalidad ir cargando los distintos componentes de una clase a medida que lo vamos usando. Esos componentes en EF se representan por medio de las llamadas propiedades de navegación, las cuales nos proporcionan una forma de navegar de una asociación o relación entre dos tipos de entidades, retornando una referencia a un objeto (si la relación es de cero a uno o uno a uno) o una colección (si la relación es de uno a muchos).

En nuestro ejemplo las propiedades de navegación son: Eventos que pertenece a la clase Agenda y Agenda que pertenece a la clase Evento:

1:     public class Agenda
2:     {
3:         public int AgendaId { get ; set ; }
4:         public string Propietario { get ; set ; }
5:         public DateTime FechaCreacion { get ; set ; }
6:
7:         public virtual ICollection <Evento> Eventos { get ; set ; }
8:     }
1:     public class Evento
2:     {
3:         public int EventoId { get ; set ; }
4:         public int AgendaID { get ; set ; }
5:         public DateTime Fecha { get ; set ; }
6:         public string Comentario { get ; set ; }
7:
8:         public virtual Agenda Agenda { get ; set ; }
9:     }

Notece que por convención dichas propiedades son marcadas como virtual (si no las marcamos de esta forma, no podremos aprovechar las ventajas de LazyLoad).

Antes de escribir nuestra primer linea de código, quiero comentarles que Lazy Loading en EF 4 viene habilitada por default. Esto no es del todo apropiado, sobre todo cuando el volumen de datos es demasiado grande o en el caso de que solo quiera recuperar, por ejemplo, un listado de agendas, donde no me interesa conocer todos sus eventos asociados. Para evitar esto, vamos a decirle al DbContext que por defecto esta característica – LazyLoadingEnabled – venga des-habilitada. Entonces modificamos el constructor de nuestro DatosContext:

1: public class DatosContext : DbContext
2: {
3:     public DbSet<Agenda> Agendas { get; set; }
4:     public DbSet<Evento> Eventos { get; set; }
5:
6:     public DatosContext() : base("name=DatosContext") 
7:     {
8:         this.Configuration.LazyLoadingEnabled = false; 
9:     }
10: }

Ahora sí, ya tenemos nuestro entorno listo, comencemos!

Lo primero que debemos hacer es crear y grabar una agenda y luego asignarle un par de eventos (de esta forma podremos visualizar mejor los ejemplos). Una forma simple de realizar esto es sobre-escribir el método Seed() de la clase DatosInitializer tal como lo explicamos en el primer post de esta serie.

Ya conocemos la forma en que se relacionan nuestras entidades, por lo tanto vamos a hacer uso del método Include() que nos proporciona la clase DbQuery. También podemos hacer uso de la extensión Include() provisto por DbExtensions (para este caso recordemos importar System.Data.Entity).

Include() es el método que nos permite obtener de una consulta el set completo de datos de una entidad y de todas sus relaciones.

Generalmente para recuperar la lista de alguna entidad (en nuestro caso de agendas) escribimos la siguiente consulta:

1: public ActionResult Index()
2: {
3:     var agendas = datos.Agendas.ToList();
4:
5:     return View(agendas);
6: }

Sin embargo, esto no nos recupera la lista de eventos asociados a cada agenda (siempre y cuando hayamos desactivado la característica de Lazy Loading). Inspeccionando la primer agenda de la lista podemos afirmar esto:

Inspeccionando objetos obtenidos con EF4.1 sin LazyLoad

Inspeccionando objetos obtenidos con EF4.1 sin LazyLoad

Para poder recuperar la agenda y sus eventos asociados debemos hacer uso del método Include() donde le pasaremos como parametro la propiedad de navegación de la cual queremos obtener los datos:

1: public ActionResult Index()
2: {
3:     var agendas = datos.Agendas.Include("Eventos").ToList();
4:
5:     return View(agendas);
6: }

Ahora vemos los mismos objetos obtenidos con LazyLoad:

Inspeccionando objetos obtenidos con EF4.1 con LazyLoad

Inspeccionando objetos obtenidos con EF4.1 con LazyLoad

Como observamos, se han recuperado también los Eventos de la agenda.

Para finalizar veamos algunos ejemplos más de lo que podemos hacer con EF y Lazy Load:

1:// Recupero todas las relaciones entre agenda y eventos utilizando DbQuery.
2:// La asociación se especifica por medio de un string.
3:var ag = datos.Agendas.Include("Eventos").ToList();
4:
5:// Recupero todas las relaciones entre agenda y eventos utilizando DbExtensions
6:// La asociación se especifica por medio de una expresion lambda.
7:var ae = datos.Agendas.Include(e => e.Eventos).ToList();
8:
9:// Recupero una agenda creada en el día de hoy y sus eventos.
10:var a1 = datos.Agendas
11:          .Where(a => a.FechaCreacion == DateTime .Now)
12:          .Include(e => e.Eventos)
13:          .FirstOrDefault();

Espero que le haya sido de utilidad.