ASP.NET MVC y Knockout : ViewModel

Una situación muy común que nos encontramos cuando comenzamos a trabajar con Knockout y ASP.NET MVC es la inicialización del modelo de KO (estructura JS) a partir del modelo de la vista (objeto C#). Una alternativa es inicializar el modelo de KO por medio de una llamada ajax al servidor (por ejemplo invocar un servicio WebAPI que nos devuelva el modelo ya serializado). Sin embargo como explica Eric Hexter en este excelente post, la experiencia de carga de la página por medio del renderizado del servidor (server side rendering) al parecer sigue siendo la más óptima.

Por lo tanto tenemos por un lado un renderizado inicial del lado del servidor utilizando un modelo de vista para tal propósito y por el otro lado tenemos KO con su propio modelo. La pregunta es cómo transformamos el viewmodel de ASP.NET MVC al viewmodel de KO sin utilizar llamas Ajax?

Investigando un poco encontré una simple solución propuesta por Eric Hexter (ver enlace de arriba). Lo que él propone es que simplemente convirtamos el modelo de la vista en un objeto Json dentro del código javascript de la página. En el ejemplo utilizaremos el view engine Razor para tal fin.

Manos a la obra!

En primer lugar vamos a crear el método de extensión ToJson() que nos permitirá representar objetos de .NET en formato JSON:

JsonExtension

JsonExtension

Por medio de esta extensión vamos a tener disponible el modelo de la vista en formato JSON, lo que nos posibilitará utilizarlo en nuestra lógica del lado del cliente (código javascript). Ahora lo que necesitamos es mapear el objeto JSON a los objetos observables que utiliza KO. Quien nos permite realizar tal actividad es el siguiente plugin de KO: KnockoutJS Mapping plugin  (disponible por medio de Nuget):

PM> Install-Package Knockout.Mapping

Veamos qué tan simple es su uso (continuamos con el ejemplo del post anterior):

Serializando el view model.

Serializando el view model.

Algunos puntos importantes:

  • Referencias a las librerías de KO y KnockoutJS Mapping plugin.
  • Generamos la representación JSON del modelo de la vista (del servidor) por medio del método de extensión ToJSon() y lo escribimos en el script por medio del helper HTML Raw.
  • El resto debería ser historia conocida 😉

Bien, finalmente tenemos el cuerpo del documento HTML:

Estructura HTML

Estructura HTML

Y la generación – mock – del modelo (en este ejemplo en el método de acción Index del controlador Home):

Método de acción Index

Método de acción Index

Corremos la aplicación y deberíamos obtener el siguiente resultado:

Resultado :)

Resultado 🙂

Como pueden ver esta es una forma muy simple de bindear el modelo de la vista del servidor al modelo de la vista del cliente.

Espero que les sea de utilidad!

Anuncios

EntityFramework 4.3.0 Released

Recientemente salio a la luz la versión release de Entity Framework 4.3.0 y en la que ya podemos disfrutar de muchas características que seguramente estarán disponibles en la versión 5.0 que viene en camino.

Entre las principales características que podemos encontrar en versión están:

  • New Code First Migrations Feature: esta es una de las principales características de la nueva versión de EF y nos permite ir “migrando” nuestra base de datos creada con Code First a media que el modelo va cambiando. Esto quiere decir que, entre otras cosas, podemos recuperar una instancia determinada de la base de datos entre las distintas versiones (migraciones) que hayamos generado. En un próximo post vamos a ver como trabajar con esta nueva característica.
  • Removal of EdmMetadata table: como ya hemos visto, con Code First podemos crear la base de datos simplemente ejecutando la app. A la creación se le suman todas las ventajas del esquema de generación que forma parte de Migrations.
  • Data Annotations on non-public properties: por defecto Code First no incluye las propiedades protected, private o internal.  Si utilizábamos estos modificadores por medio de otras API, los Data Anottations en dichas propiedades eran ignoradas. En esta nueva versión se ha modificado esta situación por lo que las Data Anottations en esos casos serán procesadas.
  • More configuration file settings: ahora es posible definir muchas más caracteristicas sobre Code First en nuestro archivo de configuración. Todos los detalles aquí.

Instalación desde Nuget:

Instalando EF desde la consola de Nuget

Instalando EF desde la consola de Nuget

Más info sobré la instalación: http://nuget.org/packages/entityframework

Algunos enlaces interesantes sobre el tema:

ASP.NET MVC 3 y Structure Map

Como ya hemos hablado en otros post, una de las características que nos permiten mejorar el código de nuestros desarrollos es la utilización de patrones de diseño. Uno de esos patrones es la Inyección de Dependencias que consiste en suministrar objetos a una clase en lugar de ser la propia clase quien cree el objeto.

En este post voy a mostrarles un framework llamado Structure Map que nos permite aplicar este patrón en nuestros proyectos .NET y la forma de integrarlo al soporte de IoC que provee ASP.NET MVC 3.

Structure Map es un framework para .NET que nos permite trabajar con Inyección de Dependencias e Inversión de Control.

El primer paso sera agregar las referencias a la librería de Structure Map. Para ello vamos a instalarlas utilizando Nuget:

Agregando la librería Structure Map

Agregando la librería Structure Map

Es importante recordar que la pieza central respecto al soporte de IoC que provee ASP.NET MVC 3 es la interfaz IDependencyResolver que nos permite “conectar” distintos motores de IoC con tan solo implementarla en una clase y luego registrarla.

En nuestro ejemplo vamos a crear nuestro propio Dependecy Resolver que va a ser manejado con Structure Map. Para ellos vamos a crear la clase StructureMapDependencyResolver que, como dijimos anteriormente, implementará IDependencyResolver:

1: public class StructureMapDependencyResolver : IDependencyResolver
2: {
3:     private IContainer container;
4:
5:     public StructureMapDependencyResolver(IContainer container)
6:     {
7:         this.container = container;
8:     }
9:
10:     public object GetService(Type serviceType)
11:     {
12:         if (serviceType.IsAbstract || serviceType.IsInterface)
13:         {
14:             return this.container.TryGetInstance(serviceType);
15:         }
16:         else
17:         {
18:             return this.container.GetInstance(serviceType);
19:         }
20:     }
21:
22:     public IEnumerable<object> GetServices(Type serviceType)
23:     {
24:         return this.container.GetAllInstances<object>()
25:             .Where(s => s.GetType() == serviceType);
26:     }
27: }

Lo que hicimos aquí fue implementar los siguiente métodos:

En ambos métodos hemos utilizado el contedor IContainer (que nos provee la librería Structure Map) cuya finalidad es la de registrar y resolver las dependencias que hayamos definido.

Bien, ahora vamos a crear una interfaz bien simple, la cual denominaremos IMessage:
1: public interface IMessage
2: {
3:     string GetMessage();
4: }

Y dos implementaciones bien sencillas de la misma, la primera la llamaremos HelloMessage:

1: public class HelloMessage : IMessage
2: {
3:     public string GetMessage()
4:     {
5:         return "Buenos días!" ;
6:     }
7: }

Y la segunda ByeMessage:

1: public class ByeMessage : IMessage
2: {
3:     public string GetMessage()
4:     {
5:         return "Hasta mañana!" ;
6:     }
7: }

Llego el momento de registrar a nuestro “resolvedor(?) de dependencias”  🙂 y para ello debemos agregar las siguientes lineas en el archivo global.asax:

1: public class MvcApplication : System.Web.HttpApplication
2: {
3:     public static void RegisterGlobalFilters(GlobalFilterCollection filters)
4:     {
5:         filters.Add(new HandleErrorAttribute());
6:     }
7:
8:     public static void RegisterRoutes(RouteCollection routes)
9:     {
10:         routes.IgnoreRoute("{resource}.axd/{*pathInfo}" );
11:
12:         routes.MapRoute(
13:             "Default", // Route name
14:             "{controller}/{action}/{id}", // URL with parameters
15:             new { controller = "Home" , action = "Index" } 
16:         );
17:
18:     }
19:
20:     protected void Application_Start()
21:     {
22:         AreaRegistration .RegisterAllAreas();
23:
24:         RegisterGlobalFilters(GlobalFilters.Filters);
25:         RegisterRoutes(RouteTable.Routes);
26:
27:         InitializeContainer();
28:     }
29:
30:     public void InitializeContainer()
31:     {
32:         var c = InitContainer();
33:         DependencyResolver.SetResolver(new StructureMapDependencyResolver(c));
34:     }
35:
36:     private static IContainer InitContainer()
37:     {
38:         var container = new Container();
39:
40:         container.Configure(s => s.For<IMessage>().Use<HelloMessage>());
41:
42:         return container;
43:     }
44: }

Dentro del método Application_Start() invocamos un nuevo método llamado InitializeContainer() en el cual vamos a registrar StructureMapDependencyResolver como el encargado de resolver las dependencias. Previamente a este paso hemos creamos el método InitContainer() en el cual hemos creado un objeto Container al cual le fuimos configurando el mapeo entre interfaces y clases que sera utilizado para poder resolver las dependencias (en el ejemplo solo es uno y es el de IMessage).

Es hora de crear el controlador HomeController cuyo constructor recibirá como parámetro un IMessage el cual será “inyectado” cada vez que sea instanciado (de lo cual ya no debemos preocuparnos gracias a IDependencyResolver). También vamos a definir un método de acción Index:

1: public class HomeController : Controller
2: {
3:     private IMessage MessageService { get ; set ; }
4:
5:     public HomeController(IMessage service)
6:     {
7:         this .MessageService = service;
8:     }
9:
10:     public ActionResult Index()
11:     {
12:         ViewBag.Message = MessageService.GetMessage();
13:
14:         return View();
15:     }
16: }

Ejecutamos y veremos que el servicio instancia es el que hemos definido al momento de crear el contenedor, en este caso HelloMessage:

Resultado obtenido de HelloMessage

Resultado obtenido de HelloMessage

Ahora modificamos el contenedor para instanciar el servicio ByeMessage en la interfaces IMessage:

1: private static IContainer InitContainer()
2: {
3:     var container = new Container();
4:
5:     container.Configure(s => s.For<IMessage>().Use<ByeMessage>());
6:
7:     return container;
8: }

Ejecutamos y verificamos que se invoco el servicio que definimos:

Resultado obtenido con ByeMessage

Resultado obtenido con ByeMessage

De más esta decir, que esto simplifica y mejora el código de nuestros desarrollos, ya que en el caso de que debamos modificar la referencias a nuestros servicios, y si estos mantienen el contrato, solo debemos modificar una sola línea de nuestro proyecto, y es el mapeo entre interfaz y clase que hemos configurado en el contenedor de dependencias.

Quienes quieran descargar el proyecto pueden hacerlo desde acá: MvcAndStructureMap.rar.

Espero que les sea de utilidad.

Disponible ASP.NET MVC 4 Roadmap

ASP.NET MVC

ASP.NET MVC

En el día de hoy me he encontrado con una gran noticia, y es que están por comenzar a trabajar en una nueva versión de ASP.NET MVC.

Ya podemos acceder al documento con la planificación del trabajo de ASP.NET MVC 4, el cual no es definitivo, pero nos da pautas de las nuevas características que va a ofrecer esta versión.

Uno de los objetivos es generar una de las mejores plataformas de desarrollo de aplicaciones web modernas (rich web apps) y multi-plataforma (ya veremos que varias de las características estan relacionadas a los dispositivos mobiles o tablets, como también a HTML 5).

Algunas de las características que ofrecería son:

  • Recipes (Extensible Task-Based Tooling): en ASP.NET MVC 4 un Recipe es básicamente una caja de dialogo entregada vía Nuget para implementar ciertas carateristicas automaticamente, como por ejemplo: Ajax grid, autentificación mediante OAuth o claims utilizando Windows Identity Framework (WIF) entre otros. La idea es que uno también pueda escribir sus propios Recipe y reutilizarlos en otras aplicaciones.
  • Mobile Support: en los nuevos proyectos web tendremos plantillas CSS optimizadas para la visualización de nuestro sitio en dispositivos móbiles y tablets. También podremos crear “Mobile Applications” las cuales trabajaran con jQueryMobile para aplicaciones que estan orientadas a dispositivos mobiles unicamente.
  • Razor Helpers Support: la idea es continuar utilizando el viewengine Razor y mejorar la forma de escribir Helpers para las web pages.

Pueden ver en detalle estas característicamente y muchas otras más desde aquí.

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.

Introducción Entity Framework 4.1 Code Firts

La versión 3.5 SP1 del framework .NET nos proveia de una biblioteca ORM llamada Entity Framework. Esta primera versión recibió varias criticas por parte de los desarrolladores, las cuales por suerte fueron escuchadas por el equipo de .NET. Es por este motivo que junto a la salida de .NET 4 apareció una versión mejorada llamada Entity Framework 4.1.

Entre las mejoras que se incluyen en esta nueva versión se encuentran: el manejo de clases POCO, soporte para Lazy Load, mejor calidad en las querys SQL generadas, mayor compatibilidad con Linq entre otras más.

En este post vamos a trabajar con una nueva caracteristica de EF llamada Code Firts (cuya traducción valida prodía ser “Partiendo del código“) y cuyo punto fuerte es que partiendo de nuestras clases del dominio ya podemos crear nuestro modelo ORM. Todo esto sin preocuparnos por la creación de la base de datos, el mapeo entre las entidades y la DB, los archivos XML o editores y todas las configuraciones afines.

Pero vayamos por parte, antes de comenzar con un ejemplo, vamos a crear un proyecto ASP.NET MVC 3 y agregar las referencias a esta librería. Para poder trabajar con EF 4.1 Code First antes vamos a tener que instalar el componente EFCodeFirst y podemos hacerlo de una manera muy sencilla utilizando Nuget (en la pestaña online\all buscamos dicho componente e instalamos).

Instalando EF4.1 desde Nuget

Instalando EF4.1 desde Nuget

Finalizada nuestra instalación se nos abrirá un archivo ReadMe con algunos comentarios sobre el producto y se habrán agregado a la solución los assemblies correspondientes.

El segundo paso sera crear las entidades del modelo, en este ejemplo vamos a trabajar con dos entidades muy simples, la primera representara una agenda y la segunda eventos de la misma. Estas clases a crear son objetos simples denominados POCO en el ambiente .NET (es importante que estas clases POCO respeten algunas convenciones que no son para nada complejas y que nos permitirán trabajar con EF).

Es el turno de definir las clases que compondran nuestro modelo:

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:     }

Algo interesante a comentar de estas entidades es que las propiedades definidas como virtual corresponden a propiedades de navegación, y son aquellas que se pueden cargar en “diferido” (en otro post vamos a ver de que se trata esto).

El segundo paso será crear un contexto que nos permita realizar operaciones CRUD sobre nuestras instancias de Agenda y Evento. Para esto vamos a crear una clase llamada DatosContext que derive de DbContext y que contendra dos propiedades publicas (una por cada entidad del modelo que hemos creado) que seran del tipo DbSet<T>:

1: using System.Data.Entity;
2:
3: namespace MvcAndEF.Models
4: {
5:     public class DatosConext : DbContext
6:     {
7:         public DbSet<Agenda> Agendas { get ; set ; }
8:         public DbSet<Evento> Eventos { get ; set ; }
9:     }
10: }

Como ya se habran dado cuenta, estas librerias pertenecen a System.Data.Entity y son provistas por EF4.1. Las clases DbContext y DbSet nos permitiran realizar las operaciones relacionadas con el acceso a los datos.

A pesar de todo esto aún no hemos creamos la base de datos y mucho menos un mapeo con la misma, tampoco hemos utilizamos diseñadores y mucho menos realizamos configuraciones. Sin embargo ya estamos listo para trabajar! 🙂

Cómo es posible esto?… la respuesta es bastante sencilla, EF 4.1 Code First esta pensado para trabajar por convenciones en lugar de configuraciones (es por eso que al crear nuestras clases POCO tuvimos en cuenta ciertas consideraciones). El resto es historia conocida: cada clase se corresponderá con una tabla, cada propiedad una columna de la misma y cada instancia de dichas clases representará un registro en la base de datos.

Para ver en funcionamiento nuestro contexto, vamos a trabajar sobre un nuevo controlador llamado AgendaController y en las diferentes acciones armaremos consultas para persistir y recuperar los datos de nuestro modelo:

1: using System.Linq;
2: using System.Web.Mvc;
3: using MvcAndEF.Models;
4:
5: namespace MvcAndEF.Controllers
6: {
7:     public class AgendaController : Controller
8:     {
9:         DatosContext datos = new DatosContext();
10:
11:         public ActionResult Index()
12:         {
13:             var agendas = from a in datos.Agendas
14:                           select a;
15:
16:             return View(agendas.ToList());
17:         }
18:
19:         public ActionResult Create()
20:         {
21:             return View();
22:         }
23:
24:         [HttpPost]
25:         public ActionResult Create(Agenda model)
26:         {
27:             if (ModelState.IsValid)
28:             {
29:                 datos.Agendas.Add(model);
30:                 datos.SaveChanges();
31:
32:                 return RedirectToAction("Index");
33:             }
34:
35:             return View(model);
36:         }
37:
38:         public ActionResult Edit(int id)
39:         {
40:             var agenda = datos.Agendas.Single(a => a.AgendaId == id);
41:             return View(agenda);
42:         }
43:
44:         [HttpPost]
45:         public ActionResult Edit(Agenda model)
46:         {
47:             if(ModelState.IsValid)
48:             {
49:                 var agenda = datos.Agendas.Single
50:                             (a => a.AgendaId == model.AgendaId);
51:                 agenda.Propietario = model.Propietario;
52:                 agenda.FechaCreacion = model.FechaCreacion;
53:
54:                 datos.SaveChanges();
55:
56:                 return RedirectToAction("Index");
57:             }
58:
59:             return View(model);
60:         }
61:     }
62: }

En cada uno de los métodos de acción podemos observar ejemplos de las consultas básicas: selección, inserción y actualización de una entidad. Lo siguiente será crear cada una de las vistas para dichos métodos (lo cual se los dejo de tarea).

Ya tenemos todo listo y aún seguimos sin noticias de la base de datos 🙂 . Pues bien, es hora de que hablemos un poco de ella.

Existen dos estrategias a seguir para definir la DB: la primera es crear el esquema de la base de datos con alguna herramienta, como por ejemplo SQL Management Studio. La segunda permitir que EF 4.1 la genere por nosotros!

Por supuesto que vamos a utilizar la última opción y para eso sera necesario que en el archivo de configuración web.config agreguemos una nueva cadena de conexión para nuestra futura base de datos (esta entrada deberá tener el mismo nombre que la clase DbContext que hemos creado, para nuestro ejemplo DatosContext):

1:  <connectionStrings>
2:  <add name="DatosContext"
3:  connectionString= "Data Source=|DataDirectory|Datos.sdf"
4:  providerName= "System.Data.SqlServerCe.4.0 "/>
5:  </connectionStrings>


Nota: en nuestro caso vamos a usar como proveedor SQL Server Compact Edition 4.0 pero podriamos utilizar SQL Sever o MySql con solo modificar dicho parámetro dentro de la cadena de conexión.

Ahora simplemente ejecutamos y ya podremos crear nuestras primeras entidades:

Nuestra app corriendo

Nuestra app corriendo

Entramos al alta de Agendas:

Formulario de alta

Formulario de alta

Y creamos nuestra primer entidad:

Agregando nuestra primer entidad

Agregando nuestra primer entidad

Como podemos ver, los datos se guardaron sin necesidad de tener que crear manualmente la DB. Validemos esto abriendo el explorador de soluciones:

Base de datos creada

Base de datos creada

EF para generar automaticamente nuestra base de datos buscara dentro del archivo de configuración una cadena de conexión que tenga el mismo nombre que la clase heredada de DbContext y utilizando esta información creará el archivo correspondiente:

Modelo sobre el cual EF se basa para crear la DB

Modelo sobre el cual EF se basa para crear la DB

Podremos inspeccionar la base de datos desde el explorador de servidores (para poder visualizar la DB creada con SQL Server CE 2.0 deberemos instalar previamente el Visual Studio 2010 SP1):

Estructura de la DB creada

Estructura de la DB creada

La tabla EdmMetadata contiene información acerca de la estructura de los objetos del modelo utilizados al momento de crear la base de datos.

Para finalizar, supongamos que tenemos que modificar el modelo, deberiamos redefinir nuestra DB cierto? por defecto EF4.1 al detectar una modificación en el modelo no modifica la estructura de nuestra DB, solamente el contenido de la tabla EdmMetadata.

Para solucionar esto tenemos distintas maneras de sincronizar el modelo con la base de datos: una es hacerlo de forma manual, modificando la estructura de la tabla/s afectadas. Sin embargo existe una manera mucho mas simple para el desarrollador y es por medio del método DropCreateDatabaseIfModelChanges que viene incluida en la libería de EF4.1.

Para esto debemos agregar la siguiente línea en el método Application_Start() del archivo global.asax:

1: Database.SetInitializer<DatosContext>
2:     (new DropCreateDatabaseIfModelChanges<DatosContext>());

Como bien lo dice su nombre, este mecanismo lo que hace es eliminar y volver a crear la base de datos, por lo que todos los registros previamente grabados se perderan. Sin embargo, una forma de solucionar este problema es insertar automáticamente registros cada vez que se genere la base de datos, y la forma de hacerlo es creando una nueva clase “inicializadora” (habré inventado una nueva palabra?) que herede de DropCreateDatabaseIfModelChanges<T> donde T sera DatosContext y en la cual vamos a sobre-escribir el método Seed():

1: public class DatosInitializer : 
2:              DropCreateDatabaseIfModelChanges <DatosContext >
3: {
4:     protected override void Seed(DatosContext context)
5:     {
6:         Agenda agenda = new Agenda ()
7:         {
8:             Propietario = "Sebis" ,
9:             FechaCreacion = DateTime .Now
10:         };
11:
12:         context.Agendas.Add(agenda);
13:     }
14: }


Ahora solo resta modificar la línea que hemos escrito anteriormente dentro de global.asax para que cada vez que se vuelva a generar la base de datos, se inserten dichos registros:

1: Database.SetInitializer(new DatosInitializer ());


Resumiendo, EF 4.1 CF me parece muy recomendable para utilizar en desarrollos de pequeña escala, y ademas facilita  enormemente ciertas tareas al desarrollador, como por ejemplo evitar muchas de las configuraciones que siempre molestan a la hora de ponerse a programar.

En la proxima entrada vamos a ver como podemos integrar los validadores de ASP.NET MVC (Data Anottations) con EF4.1.

Espero que les sea de utilidad!

NuGet

Nuget es un gestor de paquetes Open Source que viene integrado con Visual Studio y que permite a los desarrolladores buscar, descargar, instalar, configurar y actualizar librerías en nuestros proyectos .NET de una manera limpia y transpartente.

Nuget

Nuget

Esta herramienta nos evita tener que, por cada compenete externo que querramos utilizar, buscar y descargar de la web los assemblies de la versión que estemos necesitando, instalarlos o copiarlos en nuestro equipo, agregar las referencias, probar que funcione y rezar para que esta no tenga dependencias a otras líbrerias que no tengamos (no les resulta familiar esta secuencia de pasos?).

Es importante destacar que Nuget esta disponible para todas las versiones de Visual Studio 2010, pero no para versiones anteriores del IDE.

Vamos a ver un ejemplo sencillo agregando a nuestro proyecto ASP.NET MVC3 un paquete de librerias que nos permita integrar twitter. Tenemos dos formas de instalar nuestros paquetes con Nuget, utilizando la interfaz gráfica o la consola.

Veamos la primer opción, para eso vamos a la carpeta Reference, hacemos click derecho sobre la misma y elegimos la opción “Add Library Package Reference“. Esto nos va a abrir la siguiente interfaz:

Interfaz gráfica de Nuget

Interfaz gráfica de Nuget

Ahora hacemos click en la pestaña “Online” y procedemos a buscar librerías relacionadas a twitter. Del listado de componentes encontrados vamos a instalar Twitter Helper, componente que nos permite agregar widgets de twitter de una manera muy sencilla. Por lo tanto seleccionamos el paquete y hacemos click en el botón “Install”:

Instalando nuestro primer paquete con Nuget

Instalando nuestro primer paquete con Nuget

Instalado el componente, vamos a hacer una simple prueba utilizando algunos de los widgets del helper sobre una vista de nuestro proyecto. En este caso vamos a mostrar una caja de busqueda por el hashtag “Nuget” y para eso vamos a escribir lo siguiente:

1: <h2> @ViewBag.Message</h2>
2: <p>
3:  To learn more about ASP.NET MVC...
4:   @TwitterGoodies.Search("Nuget")
5: </p>

Ejecutamos y veremos el widget en acción!

Widget en acción!

Widget en acción!

Simple, no? 🙂

Bien, la otra alternativa para usar Nuget es por medio de la consola integrada a Visual Studio. La misma la podremos abrir desde menu “Tools\Library Package Maneger\Package Manager Console“.

Desde la consola podremos instalar nuestros paquetes escribiendo el siguiente comando “PM > Install-Package Twitter.Helper”. En nuestro caso nos mostrara un mensaje de advertencia ya que hemos instalado el paquete previamente.

Instalando nuestro paquete desde la consola

Instalando nuestro paquete desde la consola

Ademas de esta línea de comando tenemos a disposición muchas otras, como por ejemplo para la busqueda de paquetes.

Espero que les sea de utilidad!