[Entity Framework] Model First – Parte II – Tipos Complejos

Hola, en el anterior post de esta serie vimos a manera de introducción como se trabaja Model First con Entity Framework y quedamos en las propiedades escalares.

En esta entrada hablare sobre un tipo de propiedad muy interesante que manejan las entidades de Entity Framework y como se reflejan estas no solo en el EDMX sino en la base de datos.

– Propiedades de tipo complejo [Complex Type]

Sobre el proyecto que ya teníamos [el del post anterior], sobre la entidad que teníamos agregaremos una nueva propiedad del tipo Complex Type, que ha grandes rasgos se podría definir como un contenedor de propiedades escalares y de otras propiedades complejas siempre y cuando no incurra en referencias circulares [una definición mas formal aquí] . Para agregar una propiedad de este tipo sobre una entidad, lo podemos hacer de dos formas, tomar las propiedades que deseamos estén en un tipo complejo y crear un complex type a partir de estas:

 

O bien, en el Model Browser crear un tipo complejo y agregarle a este todas las propiedades que queramos, así:

Esto nos habrá creado en nuestro EDMX en la seccion del CSDL algo como:

Name=”NombrePropiedad” >
Type=”Int32″ Name=”NombrePropiedadEscalar” Nullable=”false” />
</ComplexType>

Y del lado del código que consume este modelo, vemos algo muy curioso… y es que podemos crear instancias de nuestras propiedades de tipo complejo 🙂 es decir, son una clase mas sin ser parte de nuestras entidades de dominio y con lo cual podemos pasar grandes cantidades de información sin pasar entidades completas, haciendo uso de los objetos que obtenemos a partir de estas.

– Crear una base de datos a partir de un modelo conceptual:

Ya para finalizar, veamos como podemos a partir de nuestro modelo conceptual generar una base de datos física en un motor SQL Server, si SQL Server :S resulta que en la versión 4.0 de esta tecnología el concepto de Model First solo aplica para este motor y el script generado por el wizard lo señala Script for SQL Server 2005, 2008, and Azure, en la web se encuentra poca documentación y lo único que he visto funciona, es definir los conection strings a mano y reconstruir algunas cosas en los xml del .EDMX.

En el Entity Data Model Designer hacemos click contrario y seleccionamos la opción Generate database from Model, ha continuación se despliega el Wizard para esta operación, generamos una nueva conexión a un almacén de datos Existente, este wizard nos muestra una preview del Script generado y al finalizar vemos que nos ha creado un archivo .SQL y que nos a abierto una ventana con este script, lo que sigue es abrir la conexión y ejecutar el script.

Una vez hecho esto, si vemos en nuestro SQL Server veremos que efectivamente se ha creado la tabla que deseábamos con las propiedades que habíamos enviado, y las propiedades de tipo complejo… pues se generan como cualquier otra columna.

Espero les sea de utilidad

Hasta el próximo post.

 

 

 

[Entity Framework] Model First – Parte II – Tipos Complejos

[Entity Framework] Model First – Parte I – Introducción

Hola, una de las características que presenta Entity Framework es la posibilidad de  definir un modelo conceptual y trabajar sobre este para luego crear un almacén físico de datos. Las ventajas de esto, refuerzan sin duda el porque de esta ORM, y es que la posibilidad de desarrollar toda la lógica del aplicativo sin preocuparse por que la soportara o como o quien, le da la posibilidad al desarrollador de aplicar todo su tiempo en lo que mejor sabe hacer 🙂 .

Pero bueno, vamos a la acción, en una solución en blanco de VS 2010 agregamos dos proyectos uno de presentación y otra librería de clases, sobre la librería de clases agregamos un elemento de ADO.NET Entity Data Model pero no como siempre lo hacemos, en esta ocasión lo crearemos vacío:

Sobre el Entity Data Model Designer no se ve nada 😀 y es aquí donde podremos empezar a agregar nuestras entidades:

Al querer agregar una entidad se pedira la siguiente información:

Indicamos un nombre [este sera el nombre de la clase], el tipo base [aun no tenemos uno para implementar], el entity set define un contenedor lógico para las instancias de nuestro tipo de entidad, y el nombre que le definamos sera el que usemos en los querys cuando accedamos al contexto, por ejemplo si defino el nombre de la clase Pais y el Entity Set como nación, las consultas lucirían de esta manera:

Listpaises = (from n in context.Nacion select n).ToList();

Entity Framework sugiere que se maneje una llave primaria para las entidades y de hecho siempre debería ser así 🙂 , damos ok y vemos lo que nos ha creado el Entity Data Model Designer.

Sobre esta entidad que se ha creado podemos agregar mas propiedades, haciendo clic derecho sobre esta, Add, y seleccionando una en el menu:

Como vemos son bastantes opciones las que tenemos, en este caso trabajaremos con las propiedades Escalares, que nos permiten utilizar los tipos de datos que maneja el framework.

Hasta el próximo post.

[Entity Framework] Model First – Parte I – Introducción

[Entity Framework] Conexion con multiples proveedores en un mismo Edmx

Hola, una de las características por las que siempre veo preguntas en los foros es con respecto a si Entity Framework permite la conexión con distintos proveedores de base de datos, por ejemplo, tener una aplicación que por defecto se conecta a una base de datos en SQL Server y tener la opción de conectarla con una MySQL, la respuesta a este interrogante es SI :D.

En el siguiente ejemplo trabajare con una base de datos en SQL Server que tiene las tablas Pais y Ciudad.

Creamos un nuevo proyecto en Visual Studio, en mi caso sera uno del tipo Aplicación de Consola, sobre este proyecto agregaremos un modelo de Entity Framework y nos conectaremos a nuestra base de datos hecha en SQL Server.

Una vez hecho esto, como de costumbre se habrá generado un archivo de configuración que contiene el ConnectionString que usara el modelo conceptual de EF, si analizamos este archivo veremos tres cosas relevantes:

Como se puede ver tenemos [y como ya lo hemos hablado en esta serie de post] se define la metadata, donde se define la localización de los tres archivos que componen nuestro EDMX, ademas se define el Provider especifico para esta conexión y finalmente la cadena de conexión a el almacén de datos físico.

Intuitivamente lo que necesitaríamos para conectarnos con la base de datos en MySQL seria simplemente escribir un ConnectionString para esta y pasarlo como parámetro en el constructor del contexto. Pero si hacemos esto recibiremos una excepción informándonos que no se puede convertir el resultado de MySQLClient a uno de SQLClient, pero ¿por que?…. la respuesta esta en la estructura de los archivos XML que maneja Entity Framework para construir el EDMX.

Si revisamos el post de introducción de esta serie veremos que allí se nombran estos tres archivos y se explica que el archivo .ssdl (Storage Schema Definition Language) es el encargado de describir la estructura física de la base de datos, incluyendo la definición de las tablas, las vistas, SP’s y relaciones.

Teniendo esto clara la teoría solo falta verlo en acción, para ver el XML de un archivo EDMX, basta con hacer click contrario en el archivo, hacer click en la opción Open With y seleccionar XML (Text) Editor. Si revisamos el XML generado desde la sección del comentario SSDL Content nos daremos cuenta de lo que trata este XML. Como vemos en el elemento Schema se define:

Provider=”System.Data.SqlClient” ProviderManifestToken=”2008″

Es por esto que por mas que cambiemos el conecctionstring obtendremos una excepción.

La solución a esto, simple, escribir nuestro propio .ssdl que contenga la definición para MySQL, lo que debemos hacer es agregar un nuevo archivo de xml con el nombre ModeloMySql.ssdl y copiar y pegar el contenido que esta definido desde el comentario SSDL Content, eliminamos la etiqueta edmx:StorageModels. Una vez hecho esto redefiniremos los valores de las propiedades : Provider, ProviderManifestToken y Schema [este ultimo en MySQL toma como valor el nombre de la base de datos]. Nuestro archivo quedaría así:

Namespace="EFDemoModel.Store" Alias="Self" Provider="MySql.Data.MySqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">

Una vez hecho esto deberemos crear el connectiostring que se conecte a la base de datos MySQL yque ademas use nuestro archivo .SSDL, así:

name="efdemomysqlEntities"
         connectionString="metadata=ModeloMySql.ssdl|res://*/Modelo.csdl|res://*/Modelo.msl;provider=MySql.Data.MySqlClient;provider connection string="server=localhost;User Id=root;password=root;database=efdemomysql""
         providerName="System.Data.EntityClient" />

Notese que no le he dado ningun carácter de escape para la localización del archivo, esto se debe a que en las propiedades del archivo en la propiedad copiar en el directorio de resultados le asigne SIEMPRE. mas información sobre las propiedades de archivos aquí.

Una vez hecho esto solo nos resta probar su funcionamiento, del lado del código de nuestra interfaz de usuario he hecho lo siguiente:

string conexionMySql = ConfigurationManager.ConnectionStrings["efdemomysqlEntities"].ConnectionString;
 using (EFDemoEntities context = new EFDemoEntities())
 {
                List paisesLatinos = (from p in context.Pais
                                     select p).ToList();
  }
  using (EFDemoEntities context = new EFDemoEntities(conexionMySql))
  {
                List paisesEuropeos = (from p in context.Pais
                                     select p).ToList();
   }

Ejecutamos y veremos los resultados.

Como vemos es una gran ventaja esta que nos ofrece esta ORM, pues ya no es necesario casarse con el gestor de base de datos en cuestión si no que se puede migrar en cualquier momento. [Aunque esta es la hora que no he visto un solo cliente pedir algo así].

NOTA: Para conectar Entity Framework 4.0 con MySQL se debe usar el conector 6.3.5, que se encuentra en este enlace, lo instalas y el mismo te configura el Visual Studio 2010 para tomar esta tipo de conexiones.

Espero les sea de utilidad.

Descarga el ejemplo.

Hasta el próximo post.

[Entity Framework] Conexion con multiples proveedores en un mismo Edmx

[Entity Framework] Lazy Load y SQL Profile

Hola, una de las características mas importantes de Entity Framework es la aplicación del patrón Lazi Load, que a grandes rasgos, se basa en ir cargando los distintos componentes de una clase cuando los vamos usando.

Teniendo presente esto, vale recordar otra de las características [buena y no tan buena] de Entity Framework, las propiedades de navegación, estas son las representaciones conceptuales que se tiene de una llave foránea y varían según la relación [uno a uno – uno a varios ], teniendo así por defecto un objeto o una colección de objetos de cada una de las entidades con las que se una entidad se relaciona.

El Lazy Load viene por defecto activado cuando creamos nuestro modelo de Entity Framework:

Para ver el funcionamiento de este, veamos un ejemplo:

En nuestra base de datos Pais  – Ciudad tenemos una relación de Uno a varios por lo que el objeto que deberá contener la entidad Pais en sus propiedades de navegación es una colección de Ciudad, y Ciudad deberá tener un objeto de Pasi en sus propiedades de navegación. Si ejecutamos una consulta en la que se recupera todo una colección de paises y en debug exploramos lo que en esta hay, veremos que se ha cargado una colección de Ciudad en nuestros objetos Pais.

En el post anterior de esta serie vimos como obtener el código SQL que se generaba a partir de una consulta Linq, otra forma de hacerlo es con las herramientas de performance de los motores de base de datos, en este ejemplo lo haré con SQL Server 2008.

Para abrir el Sql Server Profiler se debe ir a inicio – todos los programas – Microsoft Sql Server 2008 R2 – Performance tools, así:

Creamos un nuevo Trace, le asignamos un nombre y empezamos a trabajar:

Si ejecutamos la consulta anterior, veremos que en el Profiler no se marca mas que una consulta, ¿por que? bien esa es la “magia” de el Lazy Load, como no hemos requerido de este objeto [colección de Ciudades] pues no se ha mandado a ejecutar ninguna otra consulta, basta con desplegar el explorador de objetos en modo debug para que se requiera ejecutar otra consulta y cargar así, otra colección u objeto:

Como vemos al desplegar las propiedades de un objeto Pais que contiene una colección de tipo Ciudad se manda a ejecutar una sentencia adicional, esta sentencia dependerá de el proveedor especifico que se este manejando, en este caso SQL Server.

Teniendo en cuenta lo anterior ya sabemos que es lo que pasa con sentencias de este tipo [imagen], se debe ir dos veces a la base de datos, asi se trabaje con una colección y no directamente con el contexto.

– Lazy Load Disabled

Por lo general acostumbro a trabajar con el Lazy Load deshabitado, pese a que los objetos se crean por demanda, me gusta tener el control sobre estos a mi y a nada mas :P, veamos como se comporta:

La sentencia anterior se vera reflejada en el SQL Profiler así:

Como vemos NO SE HA GENERADO una segunda sentencia SQL para traer la colección de Ciudad relacionadas con un Pais y por tanto al intentar obtener un objeto de este tipo vendrá NULL. Pero y si de verad necesitamos traernos con nosotros estas colecciones u objetos, ¿que hacemos? Simple, se acude a el método Include(), así:

Y lo que veremos en el SQL Profiler, es el resultado de el proveedor especifico, una consulta anidada :S he investigado y no cambia mucho en rendimiento contra un join por ejemplo, pero si me parece complejo (a simple vista :D).

Casi nunca necesito retornar un objeto y a la vez sus hijos, pero es una característica, no se hasta que punto elegante, pero en ocasiones muy útil.

Espero les sea de utilidad.

Hasta el próximo post.

[Entity Framework] Lazy Load y SQL Profile

[Entity Framework] Obteniendo el SQL generado por una consulta Linq

Hola, la preocupación de muchos usuarios de esta tecnología, es la de saber como se traducen nuestras consultas Linq a SQL (Standard/Structured Query Language), pues bien, para esto hay un método en la clase ObjectQuery  localizada en el espacio de nombres de System.Data.Objects que nos permite saberlo. Por ejemplo:

using System.Linq;
using System.Data.Objects;
namespace EFDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            using (efdemoEntities context = new efdemoEntities())
            {
                var query = (from p in context.pais
                             select p);
                var objectQuery = query as ObjectQuery;
                string consultaSql = objectQuery.ToTraceString();
            }
        }
    }
}

Como resultado de su ejecución se obtiene lo siguiente:

Como vemos se muestra la consulta SQL generada para esta sentencia Linq.

Espero les sea de utilidad.

Hasta el próximo post.

[Entity Framework] Obteniendo el SQL generado por una consulta Linq

[Entity Framework] Separando el Acceso a Datos de la Interfaz de Usuario, Parte II – Self-Tracking Entities – WCF

Hola, continuando con esta serie de post de este excelente ORM, llegamos al punto en el que queremos separar de una vez por todas la entidades de nuestro contexto y poder ademas consumir este, sin que la presentación conozca el acceso a datos.

Para esto, haremos uso de un nuevo elemento implementado en Visual Studio 2010 y que es especial para el trabajo con Entity Framework, se trata de Self  Traking Entities,  emplearemos un WCF quien sera el encargado del negocio, este conocerá nuestras entidades y nuestro contexto, y presentara a la interfaz de usuario el resultado de las operaciones, pero bueno basta de charla y manos al teclado.

Lo primero que haremos sera iniciar Visual Studio 2010, crearemos una solución en blanco, sobre esta agregaremos dos proyectos uno de librería de Clases [AccesoDatos] y uno de interfaz de usuario, en mi caso Consola esta bien. Sobre la class Library agregamos un elemento del tipo Entity DataModel y hacemos lo que ya sabemos hacer, conectarnos a un modelo físico.

Agregaremos sobre la solución un nuevo proyecto del tipo Class Library y lo llamaremos Entidades [Eliminamos la clase que VS nos genera por defecto].

Ahora sobre nuestro proyecto de AccesoDatos agregamos un nuevo elemento, localizado en la sección Code y que se llama ADO.NET Selft Tracking Entity Generator, este sera el encargado de crearnos, a partir de un .edmx dos plantillas t4 (.tt) con lo que necesitamos [explicación mas adelante :P].

Con esto se nos habrá generado dos ficheros de extinción .tt, el archivo <Modelo>.tt sera el que contenga nuestras entidades de dominio y ademas una clase auxiliar que contendrá en su interior la lógica del seguimiento de cambios que utilizan las entidades de Selft Tracking Entities y los métodos de extensión que permiten establecer el estado de estas. El archivo <Modelo>.Context.tt genera una clase ObjectContext con tipo y una clase de extensión que contiene los métodos ApplyChanges para las clases ObjectContext y ObjectSet.

Ahora bien, para que nuestros ficheros tt’s conozcan el Modelo conceptual debemos definirlo en las lineas:

string inputFile = @”ModeloDemo.edmx”;

Adicional podemos eliminar el Custom Tool del modelo conceptual, pues ya no lo usaremos mas 😀

Lo siguiente sera separar las entidades de esta librería, para esto, cortamos la t4 que contiene las entidades y las pegamos sobre el proyecto Entidades. Una vez hecho esto, se debe cambiar  la definición de el valor inputfile de este, pues ya no se encuentra en la misma carpeta, e mi caso seria así:

string inputFile = @"..\AccesoDatos\ModeloDemo.edmx";

Lo que sigue es sobre el proyecto Entidades agregar una referencia al ensamblado System.Runtime.Serialization, pues estas entidades que nos genera son serializables. Como paso final Agregaremos una referencia de nuestro proyecto de Entidades a el proyecto de AccesoDatos, pues el contexto debe conocer a sus entidades de domino y en la plantilla t4 debemos indicar que se debe hacer uso de esta, para eso definimos a manera de string un segundo parametro en la linea WriteHeader(), así:

WriteHeader(fileManager, "NombreEnsamblado");

En este momento nuestra solución debería lucir así:

[Nota: debe verse ademas el App.Config en el proyecto de AccesoDatos no se ve aquí porque es una demo ya terminada :D]

Como paso siguiente agregaremos un nuevo proyecto a solución, este sera un WCF Service Application, así:

Sobre este proyecto agregaremos una referencia a los ensamblados de Entidades y AccesoDatos, ademas sera necesario agregar una referencia a el ensamblado System.Entity.Data y copiar la Connection String de nuestro App.Config de el proyecto AccesoDatos a el Web.Config de nuestro WCF. el App.Config puede ser eliminado sin problemas de nuestro proyecto de AccesoDatos.

Del lado del código, en la definición del servicio definiremos los métodos necesarios para trabajar con nuestras entidades, así:

using System.Collections.Generic;
using System.ServiceModel;
using Entidades;
namespace WCF
{    
    [ServiceContract]
    public interface IEfDemo
    {
        [OperationContract]
        List<Pais> ObtenerPaises();

        [OperationContract]
        int Modificar(Pais pais);

        [OperationContract]
        Pais ObtenerPaisPorId(int id);

        [OperationContract]
        int InsertarPais(Pais pais);

        [OperationContract]
        int ModificarPaisPorId(int id);
    }   
}

Y del lado de la implementación:
using System.Collections.Generic;
using System.Linq;
using Entidades;
using AccesoDatos;
namespace WCF
{
    public class Service1 : IEfDemo
    {
        public List ObtenerPaises()
        {
            using (EFDemoEntities context = new EFDemoEntities())
            {
                return (from p in context.Pais
                        select p).ToList();
            }
        }
        public int Modificar(Pais pais)
        {
            using (EFDemoEntities context = new EFDemoEntities())
            {
                context.Pais.ApplyChanges(pais);
                return context.SaveChanges();
            }
        }
        public Pais ObtenerPaisPorId(int id)
        {
            using (EFDemoEntities context = new EFDemoEntities())
            {
                return (from p in context.Pais
                        where p.Id == id
                        select p).First();
            }
        }
        public int InsertarPais(Pais pais)
        {
            using (EFDemoEntities context = new EFDemoEntities())
            {
                context.Pais.AddObject(pais);
                return context.SaveChanges();
            }
        }
    }
}

Cosas a observar, el método context.Entitie.ApplyChanges():

Como paso siguiente, seleccionamos como proyecto de inicio el proyecto de WCF y ejecutamos, VS nos generara un servidor de desarrollo con la url y el puerto para nuestro servicio, luego se agrega la referencia al servicio en la interfaz de usuario [click inverso, Add Service Reference] en este caso seleccionaremos la opción Discover, Go y

Generamos una instancia del ServiceClient, apuntamos  a uno de los métodos y listos 😀 tenemos una aplicación separada en capas con servicios de WCF y Self Tracking Entities.

[Nota: Para que el método que retorna lista genérica funcione, en presentación, es necesario configurar la referencia del servicio para que sus Collection Type sean Colecciones genéricas], así:

Con esto llegamos al final del post.

Espero les sea de utilidad.

Descarga el ejemplo

Hasta el próximo post

[Entity Framework] Separando el Acceso a Datos de la Interfaz de Usuario, Parte II – Self-Tracking Entities – WCF

[Entity Framework] Separando el Acceso a Datos de la Interfaz de Usuario, Parte I

Hola, en esta nueva entrada de la serie de post de Entity Framework, vamos a ver como separar en un ensamblado distinto el acceso a datos de nuestra interfaz de usuario, Aclaro antes de continuar, este sera un post muy sencillo, pero nos servirá para comprender unas cosillas que nos servirán mas adelante. Comenzaremos con una solución en blanco de Visual Studio, a la que agregaremos un proyecto de interfaz de usuario, en mi caso usare una de aplicación de consola y un proyecto de tipo Libreria de Clases. Tu solución se vera algo así:

Sobre el proyecto de librería de clases agregaremos un nuevo elemento del tipo Modelo de Entity Framework, que por supuesto se conectara a un modelo físico de base de datos [en este caso uno de SQL Server], el modelo de base de datos es este:

La solución lucirá así:

En este caso dejaremos que nuestro contexto sea quien contenga las entidades y control de comunicación con la base de datos, y que la interfaz de usuario conozca directamente esta capa de acceso a datos.

Agregaremos sobre nuestro proyecto de interfaz de usuario una referencia a el ensamblado de AccesoDatos, así:

Sobre este mismo proyecto agregaremos una referencia al ensamblado System.Data.Entity, ¿por que? porque esta conocerá directamente al acceso a datos y deberá ser capaz de administrarlo directamente desde sus clases, así:

Si hacemos una consulta y ejecutamos en este momento obtendremos la siguiente excepción:

Pero por que?, la respuesta, simple, estamos consumiendo nuestro modelo conceptual sin proporcionarle los Connection Strings que requiere, para solucionarlo basta con cortar el app.Config de el proyecto de AccesoDatos y pegarlo en el proyecto de presentación.

Una vez hecho esto podremos ejecutar nuestras consultas directamente sobre nuestra interfaz de usuario ver los resultados:

Con esto llegamos al final de este post, se que no es muy útil, pero deja dos bases solidas para el manejo a N-Tier con Entity Framework

Hasta el próximo post.

[Entity Framework] Separando el Acceso a Datos de la Interfaz de Usuario, Parte I