ADO.NET Entity Framework: LINQ To Entities, Entity SQL y Entity Services (II)

Hace un par de semanas escribía un primer post sobre ADO.NET Entity Framework complementario a la estupenda serie de posts que sobre esta temática ha venido realizando Jorge Serrano. En este post veíamos los fundamentos de ADO.NET Entity Framework, como construir un Entity Data Model (EDM) a partir de una cierta BD, y como realizar operaciones (de selección, inserción, actualización o borrado) mediante LINQ To Entities. La idea de este post es mostraros la flexibilidad de ADO.NET Entity Framework en cuanto a que para operar contra el EDM no sólo disponemos de LINQ To Entities, sino que tenemos otras dos opciones: Entity SQL (eSQL) y Entity Services. Empecemos.

Recordando los componentes de Entity Framework

Aunque Jorge Serrano ya nos explicó los componentes de un EDM, no está de más hacer un pequeño repaso de los mismos. Como ya comenté en el post anterior, una de las ideas claves de la nueva versión de ADO.NET es ahorrar tiempo a los desarrolladores a través de reducir la cantidad de código necesario para acceder a los datos, reducir el mantenimiento, facilitar la persistencia de los datos, etc. Todo ello es posible a través de la definición del correspondiente EDM, el cuál podemos consultar de las tres formas comentadas. Como siempre, una imagen vale más que 1000 palabras:

image Como veis, la clave de la realización de operaciones contra el EDM mediante cualquiera de los tres métodos está en un nuevo proveedor de datos: el Entity Client. Este proveedor permite interactuar contra el EDM mediante eSQL, que como veremos se trata de un nuevo lenguaje muy similar a T-SQL (sólo que las sentencias se ejecutan contra el EDM), Entity Services o LINQ To SQL que en este caso interactúan con el EDM a través de un objeto ObjectQuery (que representa una consulta que devuelve un cierto objeto con los datos).

Como nos comentaba Jorge Serrano, para entender como se realizan las operaciones contra el EDM es necesario conocer los componentes claves del mismo en la forma de tres capas:

  • Conceptual, definida mediante un archivo .CSDL (Conceptual Schema Definition Language, o en otras palabras un archivo XML con información relativa a las entidades del modelo), el cuál incluye las entidades y las relaciones tal y como la capa de negocio de la aplicación las conoce.
  • De asignación, definida con MSL (Mapping Schema Language, de nuevo otro XML con la información de mapeo entre la capa conceptual y la capa lógica), establece el mapeo entre las entidades del modelo conceptual y sus correspondencias con la BD.
  • Lógica, definida con SSDL (Store Schema Definition Language), y representa el esquema de la BD

image

Realizando consultas con eSQL

Como hemos comentado, este nuevo lenguaje similar a T-SQL nos permite interactuar con el EDM de manera similar a como estábamos acostumbrados a realizar operaciones contra una cierta BD en ADO.NET 2.0: define objetos específicos para la conexión al EDM, objeto EntityConnection, para devolver los datos en una consulta de selección, objeto DBDataReader, o ejecutar comandos eSQL contra el modelo…todas las clases que siguen estos objetos están definidas en el System.Data.EntityClient. Por lo tanto, el primer paso para realizar operaciones contra el EDM vía eSQL es instanciar la clase EntityConnection especificando la correspondiente cadena de conexión, que por cierto no es nada trivial:

EntityConnection ecConexion = new EntityConnection( @”metadata=.CLIENTES_EDM.csdl|.CLIENTES_EDM.ssdl|.CLIENTES_EDM.msl;provider=System.Data.SqlClient;” + “provider connection string=’Data Source=.\SQLEXPRESS;” + “AttachDbFilename=”C:\Documents and Settings\Administrator\Desktop\Labs LINQ\Soluciones & Demos\BD\CLIENTES.mdf”;” + “Integrated Security=True;Connect Timeout=30;User Instance=True;MultipleActiveResultSets=True'” );

ecConexion.Open();

Como se observa, en la cadena de conexión es necesario especificar los distintos archivos de metadatos que configuran las distintas capas del EDM, así como la cadena de conexión para la BD. Una vez que hemos definido la cadena de conexión para el objeto EntityConnection, abrimos la conexión…esto se parece mucho al clásico ADO.NET…el siguiente paso es definir un comando eSQL mediante un objeto de tipo EntityCommand…dicho y hecho:

EntityCommand ecComando =
     new EntityCommand(“SELECT  clientes.ID_Cliente,clientes.DireccionCliente,” +
         “clientes.CiudadCliente FROM Entidades_BD_Clientes.Md_Clientes as clientes”, ecConexion);

Lo que hemos hecho es definir una sentencia eSQL, que parece T-SQL, pero que no lo es porque estamos realizando las consultas contra una entidad del EDM (en este caso Md_Clientes que pertenece al EDM Entidades_BD_Clientes)…¿y cómo ejecutamos este comando? Pues a través del método ExecuteReader (para este caso en el que estamos realizando una Select) del objeto EntityCommand anterior. Lógicamente los resultados los recogeremos para su procesado en un objeto de tipo DbDataReader:

using (DbDataReader dbdrReader =
    ecComando.ExecuteReader(CommandBehavior.SequentialAccess))
{
    while (dbdrReader.Read())
    {
        Console.WriteLine(dbdrReader[“ID_Cliente”] + “, ” +
            dbdrReader[“DireccionCliente”] + ” ” +
            dbdrReader[“CiudadCliente”]);
    }
}

Sin duda espectacular…y la salida por pantalla correspondiente es la siguiente:

image

Realizando consultas con Entity Services (u Object Services)

Finalmente, y para concluir el post, vamos a ver la tercera opción para realizar operaciones contra un EDM: los Entity Services (u Object Services). Esta alternativa permite devolver estructuras de información del EDM a través del método CreateQuery asociado al objeto ObjectContext (y que implementa una interfaz de tipo ObjectQuery<T>), que acepta una instrucción eSQL o LINQ To Entities con parámetros que define una consulta que recuperará una cierta lista de entidades. Así, un ejemplo de ejecutar una sentencia eSQL con Entity Services sería:

Console.WriteLine(“Entity Services”);
string sCiudad = “Santander”;
//ObjectQuery
ObjectQuery<ClientesModel.Md_Clientes> esQuery =
    ModeloClientes.CreateQuery<ClientesModel.Md_Clientes>
    (“SELECT VALUE c FROM Md_Clientes AS c WHERE c.CiudadCliente=@CiudadCliente”,
    new ObjectParameter(“CiudadCliente”,sCiudad));

foreach (var c in esQuery)
{
    Console.WriteLine(c.ID_Cliente);
}

Y la correspondiente salida por pantalla sería la siguiente:

image

Y hasta aquí la segunda entrega de la serie de posts sobre ADO.NET Entity Framework. En el siguiente post os presentaré una utilidad muy interesante para realizar operaciones contra el modelo. Espero que el post os haya resultado interesante.

Publicado por

Juan Carlos González

Juan Carlos es Ingeniero de Telecomunicaciones por la Universidad de Valladolid y Diplomado en Ciencias Empresariales por la Universidad Oberta de Catalunya (UOC). Cuenta con más de 12 años de experiencia en tecnologías y plataformas de Microsoft diversas (SQL Server, Visual Studio, .NET Framework, etc.), aunque su trabajo diario gira en torno a SharePoint & Office 365. Juan Carlos es MVP de Office Servers & Services desde 2015 (anteriormente fue reconocido por Microsoft como MVP de Office 365 y MVP de SharePoint Server desde 2008 hasta 2015), coordinador del grupo de usuarios .NET de Cantabria (Nuberos.Net, www.nuberos.es), co-fundador y coordinador del Grupo de Usuarios de SharePoint de España (SUGES, www.suges.es), así como co-director de la revista gratuita en castellano sobre SharePoint CompartiMOSS (www.compartimoss.com). Hasta la fecha, ha publicado 8 libros sobre SharePoint & Office 365 y varios artículos en castellano y en inglés sobre ambas plataformas.

2 comentarios en “ADO.NET Entity Framework: LINQ To Entities, Entity SQL y Entity Services (II)”

  1. Buenos días. Estoy intentando seguir tus consejos y comentarios para crear una aplicación usando Entity framework. La aplicación está separada en capas y la duda es ¿cuántas instancias del modelo de entidades (el ObjectContext) debe haber en la aplicación?. Si cada vez que consulto los datos creo una nueva me da problemas porque no puedo asociar entidades de una instancia con entidades de otra, y sin embargo en varios ejemplos vistos en internet lo hacen así. ¿Alguna sugerencia?

    Gracias y sigue así con tus posts que son muy buenos

  2. Buenas Atag,
    Deberías tener una instancia de ObjectContext para esas operaciones en las que quiereas asociar entidades porque EF preserva la identidad de entidades, por lo que ante ObjectContext diferentes tiene sentido lo que te está pasando.

    Un saludo

    JC’s

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *