Entity Framework

Anuncio
Marcos de Desarrollo
Diseño e implementación de aplicaciones Web con .NET
Objetivos
 Conocer los componentes del Entity Framework y su
funcionamiento
 Saber crear un modelo de datos en Entity Framework
 Aprender a realizar consultas sobre el modelo de datos en
Entity SQL y LINQ to Entities
 Conocer una implementación de un DAO Genérico
implementado con Entity Framework
Introducción Entity Framework
Programar contra un modelo, no contra la BB.DD.
 EF evita pensar en la estructura de la BB.DD.
 Acceso a datos y almacenamiento se hacen contra modelo conceptual
 EF usa Entity Data Model (EDM)
 Con tecnologías anteriores (DataReaders, DataSets) es necesario
escribir código de acceso a datos y transformar estos datos en objetos
del dominio
 EF permite recuperar directamente objetos del dominio y persistir los
cambios cuando es necesario
Introducción Entity Framework
Entity Data Model (EDM)
 Es un modelo de datos del lado del cliente
 Es el núcleo del EF
Introducción Entity Framework
Entity Data Model (EDM)
 Esquema de un conjunto típico de tablas en BB.DD.
Introducción Entity Framework
Entity Data Model (EDM)
 Consulta T-SQL para recuperar registros de
SalesPerson, junto con sus detalles personales
SELECT
FROM
SalesPerson.*, PersonalDetails.*, Person.*
Person
INNER JOIN PersonalDetails
ON Person.PersonID = PersonalDetails.PersonID
INNER JOIN SalesPerson
ON Person.PersonID = SalesPerson.PersonID
Introducción Entity Framework
Entity Data Model (EDM)
 Datos de persona modelados para encajar con los
objetos de dominio
Introducción Entity Framework
Entity Data Model (EDM)
 Consulta sobre objetos del dominio que devolverá un
conjunto de objetos SalesPerson
from p in People.OfType<SalesPerson>
select p
Introducción Entity Framework
Entities
 Los ítems descritos por un EDM se conocen como
entidades o entities.
 Las clases generadas a partir de las entidades se
conocen como clases de entidad (entity classes) y sus
instancias objetos de entidad (entity objects).
 Tienen propiedades, pero no comportamiento (salvo
seguimiento de cambios).
 Equals(), toString(), getHashCode()
Introducción Entity Framework
Entities
 Diagrama de clases de entidad
Introducción Entity Framework
Proveedores de Bases de Datos
 El API de SqlClient incluida en VS 2008 SP1 y VS 2010 soporta EF
 Se puede usar SQL Server 2005 y 2008 (full y Express)
 SQL Server CE versión 3.5 y superiores también soportan EF
 Hay más proveedores disponibles, que permiten usar Oracle,
IBM databases, SQL Anywhere, MySQL, SQLite, VistaDB y
muchas otras
 Pueden ser desarrollados por los propios vendedores de BB.DD. o
por terceros
 Lista de proveedores proporcionada por MS:
http://msdn.microsoft.com/en-us/data/dd363565.aspx
Introducción Entity Framework
Características principales
 Además del EDM, Entity Framework proporciona una
serie de APIs y herramientas
 Metadatos
 Herramientas de Diseño del EDM
 Object Services
 Seguimiento de cambios
 Gestión de las relaciones y claves foráneas
 EntityClient
Introducción Entity Framework
Características principales
 Metadatos
 El modelo de datos conceptual se almacena en fichero XML
 Este fichero también guarda una definición del esquema de la
BD y las relaciones con el modelo conceptual
 EF es capaz de traducir consultas sobre el modelo a consultas
sobre la BD y transformar los resultados obtenidos a objetos
del modelo, consultado estos metadatos
Introducción Entity Framework
Características principales
 Herramientas de diseño del EDM
 EDM designer: permite trabajar con el modelo de entidades de
forma visual, sin necesidad de tener que manipular el XML

Soporta las características más usadas

VS 2010 muchas más características que VS 2008 SP1

Incluye EDM Wizard: permite generar un modelo a partir de una BD
existente (database first)

VS 2010 permite crear el modelo en el diseñador y generar el esquema de
la BD de forma automática (si lo soporta el proveedor) (model first)

Generador de código:

se generan clases de forma automática a partir del modelo
Introducción Entity Framework
Características principales
 Object Services
 Proporcionan clase EntityObject
 Permiten "materializar" objetos a partir de resultados de consultas
contra el EDM, realizar seguimiento de cambios en esos objetos,
gestionar relaciones entre objetos y guardar los cambios en BD
Introducción Entity Framework
Características principales
 Seguimiento de cambios (tracking)
 Una vez que un objeto entidad ha sido instanciado, los
Servicios de Objeto pueden realizar seguimiento de este
objeto
 Los Servicios de Objeto usan esta información a la hora
de actualizar los datos

Construyen comandos Insert, Update, y Delete para cada
objeto que ha sido añadido, modificado o borrado,
comparando los valores originales con los valores actuales.
Introducción Entity Framework
Características principales
 Gestión de Relaciones y Claves Foráneas
 EF 4 incorpora soporte para claves foráneas

En un modelo ER clásico, las claves foráneas no se exponen en
el modelo conceptual

La primera versión de EF (.NET 3.5 SP1) seguía este
paradigma, pero ante la demanda de los desarrolladores se
incorporó a la nueva versión
Introducción Entity Framework
Características principales
 Entity Client
 Proporciona funcionalidad para realizar consultas,
ejecutar comandos, recuperar resultados
 Se puede trabajar con EntityClient directamente o a
través de Object Services


Directamente, se obtienen resultados "tabulares"
A través de Object Services, se obtienen objetos
¿Qué ocurre con DataSets y DataReaders?
 Se pueden seguir usando
 EF usa DR, en la forma de EntityDataReader, que extiende a
DbDataReader (es lo que devuelve una consulta EntityClient)
 Se recomienda no integrar las dos tecnologías (EF y
DS/DR)
 EF encajará mejor en unos proyectos y DS o DR en otros
Marcos de Desarrollo
Diseño e implementación de aplicaciones Web con .NET
¿Por qué usar un EDM?
 BB.DD. se diseñan para ser mantenibles, seguras, eficientes
y escalables
 Datos se organizan según principios de diseño de BB.DD.
 OK desde el punto de vista de los datos, pero reto para el
desarrollador que necesita acceder a ellos
 Con EDM los desarrolladores se pueden concentrar en
objetos de negocio
 No hay que preocuparse por la estructura de la BD, nombres
de las tablas o vistas, etc.
 No hay que transformar los datos devueltos a objetos
Características del EDM del Entity Framework
 Genera clases de forma automática a partir del modelo y
las actualiza dinámicamente cuando el modelo cambia
 Gestiona de la conectividad con la B.D.
 Proporcionan sintaxis común para realizar consultas sobre
el modelo
 Traduce estas consultas en otras comprensibles por la B.D.
 Proporciona mecanismo para realizar seguimiento de
cambios en los objetos del modelo y soporta la
actualización de éstos en B.D.
Pasos para crear un EDM (1 de 8)
1. Crear un proyecto de consola
2. Añadir nuevo ítem
 Botón derecho sobre el nombre del proyecto > Add >
New Item
Pasos para crear un EDM (2 de 8)
3. Seleccionar ADO.NET Entity Data Model
Pasos para crear un EDM (3 de 8)
4. Seleccionar "Generate from database“
Pasos para crear un EDM (4 de 8)
5.
Seleccionamos una conexión
previamente configurada (p.
ej. desde VS) o creamos una
nueva.
Pasos para crear un EDM (5 de 8)
Pasos para crear un EDM (6 de 8)
La cadena de conexión se guardará
en el archivo de configuración del
proyecto (App.Config).
Nombre por defecto:
<Nombre_BD> + Entities
Es también el nombre que se le
dará al contenedor de entidades.
Pasos para crear un EDM (7 de 8)
6.
Seleccionamos los objetos de
base de datos que queremos
incluir en el modelo
Nombre por defecto del modelo:
<Nombre_BD> + Model
Pasos para crear un EDM (8 de 8)
Pasos para crear un EDM (8 de 8)
Lo veremos más
adelante
Entidades (Entities)
Entity Data Model (EDM)
• Archivo con extensión .edmx
• XML, aunque por defecto se
muestra de forma gráfica
Propiedades del Entity Container
botón derecho >
Properties
Propiedades de las entidades
sobre el nombre de la
entidad
el nombre de la entidad
siempre debe ser singular
Propiedades de las entidades
sobre el nombre de la
entidad
Propiedades de navegación
Propiedades de navegación
Propiedades de navegación
Metadatos del modelo
 En el Diseñador sólo se ve la parte conceptual del
modelo, pero hay más secciones críticas del EDMX:
StorageModels y Mappings
Componentes de los metadatos del modelo del EF
.csdl: Conceptual Schema Definition Language
.ssdl: Store Schema Definition Language
.msl: Mapping Specification Language
Vista del modelo en "Model Browser"
 Se puede acceder desde
el menú contextual de la
superficie de diseño del
modelo.
 Permite ver:
 CSDL
 SSDL
Vista de los "mappings"
 Desde el menú contextual de la superficie de diseño
del modelo > "Mapping Details"
 Enlaces entre los campos de la tabla Account y las
propiedades de la Entidad Account
Vista del modelo en formato XML
 Por defecto, el fichero .edmx se abrirá en el Diseñador.
 Para ver el contenido XML, desde "Solution Explorer", sobre el
nombre del archivo, botón derecho > Open With > XML Editor
Asistente de actualización del EDM
 Permite actualizar el modelo
EDM después de que se
hayan realizado cambios
en la BD
 Desde el menú contextual de
la superficie de diseño del
modelo > "Update from
database"
Marcos de Desarrollo
Diseño e implementación de aplicaciones Web con .NET
Formas de consultar el EDM
 LINQ to Entities
 Entity SQL
 Métodos especiales
 basados en LINQ
 basados en la clase ObjectQuery
 EntityClient
Arquitectura y componentes
Componentes de la arquitectura de EF
Una consulta sencilla
 Usando tipado implícito
static void Main(string[] args)
{
using (var context = new TestEntities())
{
var accounts = context.Accounts;
foreach (var account in accounts)
{
Console.WriteLine("Acc ID: {0}, Balance: {1}",
account.accId, account.balance);
}
}
}
Una consulta sencilla
 Usando tipado explícito
static void Main(string[] args)
{
using (TestEntities context = new TestEntities())
{
ObjectSet<Account> accounts = context.Accounts;
foreach (Account account in accounts)
{
Console.WriteLine("Acc ID: {0}, Balance: {1}",
account.accId, account.balance);
}
}
}
Generación de código basado en el modelo
 El Diseñador del EDM genera
automáticamente código basado en el
modelo
 El código generado se almacena en un
archivo .Designer.cs
 Lee la capa conceptual del modelo y crea
a partir de ella una clase ObjectContext
(TestEntities en el ej.) basada en el
EntityContainer, y luego una clase
entidad para cada entidad en el modelo
(Account y AccountOp en el ejemplo)
ObjectContext y clases entidad
Consultas con LINQ to Entities (1 de 3)
 Ej.: consultar cuenta con accID = 1
using (TestEntities context = new TestEntities())
{
var accounts = from a in context.Accounts
where a.accId == 1
select a;
foreach (Account account in accounts)
{
Console.WriteLine("Acc ID: {0}, Balance: {1}",
account.accId, account.balance);
}
}
Consultas con LINQ to Entities (2 de 3)
 Ej.: consultar número de cuentas de un usuario
using (TestEntities context = new TestEntities())
{
int result = (from acc in context.Accounts
where acc.usrId == userId
select acc).Count();
Console.WriteLine(result);
}
Consultas con LINQ to Entities (3 de 3)
 Ej.: Ej.: recuperar las cuentas de un usuario
(implementando Page-by-Page)
using (TestEntities context = new TestEntities())
{
List<Account> accounts =
(from a in context.Accounts
where a.usrId == userId
orderby a.accId
select a).Skip(startIndex).Take(count).ToList();
foreach (Account account in accounts)
{
Console.WriteLine("Acc ID: {0}, Balance: {1}",
account.accId, account.balance);
}
}
Consultas con Object Services y Entity SQL
(1 de 3)
 Ej.: consultar cuenta con accID = 1
using (TestEntities context = new TestEntities())
{
var queryString = "SELECT value a " +
"FROM TestEntities.Accounts AS a " +
"WHERE a.accID = 1";
ObjectQuery<Account> accounts = context.CreateQuery<Account>(queryString);
foreach (Account account in accounts)
{
Console.WriteLine("Acc ID: {0}, Balance: {1}",
account.accId, account.balance);
}
}
Consultas con Object Services y Entity SQL
(2 de 3)
 Ej.: consultar número de cuentas de un usuario
using (TestEntities context = new TestEntities())
{
String query = "SELECT VALUE a FROM Accounts AS a " +
"WHERE a.usrId = @userId";
ObjectParameter param = new ObjectParameter(“userId", userId);
int result =
context.CreateQuery<Account>(query, param).Count();
Console.WriteLine(result);
}
Consultas con Object Services y Entity SQL
(3 de 3)
 Ej.: recuperar las cuentas de un usuario
(implementando Page-by-Page)
using (TestEntities context = new TestEntities())
{
String query = "SELECT VALUE a FROM Accounts AS a " +
"WHERE a.usrId = @userId " +
"ORDER BY a.accId";
ObjectParameter param = new ObjectParameter("userId", userId);
List<Account> accounts = context.CreateQuery<Account>(query, param)
.Skip(startIndex).Take(count).ToList();
foreach (Account account in accounts)
{
Console.WriteLine("Acc ID: {0}, Balance: {1}",
account.accId, account.balance);
}
}
LINQ vs. Entity SQL
 Entity SQL
 Se creó antes que LINQ
 Disponible para todos los lenguajes de la plataforma
 Permite trabajar a nivel más "bajo" que LINQ (sin pasar por
Object Services)
 LINQ
 Variantes (LINQ XML, LINQ to Objects, …)
 Tipado fuerte
 Sólo disponible en C# y VB.NET
Arquitectura y componentes
Componentes de la arquitectura de EF
Consultas sobre EntityClient
static void EntityClientQuery()
{
using (EntityConnection c = new EntityConnection(“name=SampleEntities”))
{
c.Open();
string queryString =
“select value c from SampleEntities.Contacts as C”;
EntityCommand cmd = c.CreateCommand();
cmd.CommandText = queryString;
using (EntityDataReader edr = cmd.ExecuteReader())
{
while (edr.Read())
{
string name = edr.GetString(1);
string surName = edr.GetString(2);
Console.WriteLine(“{0}, {1}”, surname, name);
}
}
}
}
c.Close();
Marcos de Desarrollo
Diseño e implementación de aplicaciones Web con .NET
Implementación de DAOs con Entity Framework
 DAO genérico con las operaciones comunes a todas las clases persistentes:

Create, Find, Exists, Update, Remove
 Cada entidad persistente tendrá su propio DAO, que extenderá el genérico para añadir
operaciones propias
 El DAO genérico se encuentra en el proyecto ModelUtil
ModelUtil es utilizado por MiniBank y MiniPortal
 Es de tipo "Librería de clases" (.dll)

 La interfaz parametrizada del DAO genérico recibe 2 argumentos:

E, es la clase persistente para la que se implementará el DAO

PK, define el tipo del identificador de la clase persistente
 Los métodos están definidos en base a esos parámetros y no están acoplados a ninguna
tecnología de persistencia
Implementación de DAOs con Entity Framework
 Interfaz del DAO genérico
public interface IGenericDao<E, PK>
{
void Create(E entity);
/// <exception cref="InstanceNotFoundException"></exception>
E Find(PK id);
Boolean Exists(PK id);
void Update(E entity);
/// <exception cref="InstanceNotFoundException"></exception>
void Remove(PK id);
}
Implementación de DAOs con Entity Framework
 Implementación del DAO genérico con Entity Framework
public class GenericDaoEntityFramework<E, PK> :
IGenericDao<E, PK> where E : IEntityWithKey
{
// entityClass is set in the constructor of this class
private Type entityClass;
// context must be set by means of Context property
private ObjectContext context;
private String entityContainerName;
public GenericDaoEntityFramework()
{
this.entityClass = typeof(E);
}
Implementación de DAOs con Entity Framework
 Implementación del DAO genérico con Entity Framework
Inyección de Dependencias
[Dependency]
(lo veremos + adelante)
public ObjectContext Context
{
set
{
// The value of the Context property is established
context = value;
entityContainerName = (context.MetadataWorkspace.
GetItems<EntityContainer>(DataSpace.CSpace))[0].Name;
context.DefaultContainerName = entityContainerName;
// Forces the load of the metadata
context.MetadataWorkspace.LoadFromAssembly(
entityClass.Assembly);
}
get
{
return context;
}
}
Implementación de DAOs con Entity Framework
 Implementación del DAO genérico con Entity Framework
/// <summary>
/// Creates the entity key. It is needed to get primary key field name
/// from metadata.
/// </summary>
public EntityKey CreateEntityKey(PK id)
{
EntityType entityType =
(EntityType)context.MetadataWorkspace.GetType(entityClass.Name,
entityClass.Namespace, DataSpace.CSpace);
/* We assume that the DAO works only with single field primary
* key classes
*/
String primaryKeyFieldName =
((EntityType)entityType).KeyMembers.First().ToString();
// Create the entityKey
EntityKey entityKey =
new EntityKey(GetQualifiedEntitySetName(entityClass.Name),
primaryKeyFieldName, id);
return entityKey;
}
Implementación de DAOs con Entity Framework
 Implementación del DAO genérico con Entity Framework
/// <summary>
/// Returns the qualified EntitySet name (the EntityContainer name plus
/// the EntitySet name) for a given entityClassName.
/// </summary>
/// <param name="entityClassName">Type name of an entity</param>
/// <returns>The Qualified EntitySet name</returns>
public String GetQualifiedEntitySetName(String entityClassName)
{
EntityContainer container = context.MetadataWorkspace.
GetEntityContainer(context.DefaultContainerName,
DataSpace.CSpace);
EntitySetBase entitySet = container.BaseEntitySets.Where(item =>
item.ElementType.Name.Equals(entityClassName)).FirstOrDefault();
return (entityContainerName + "." + entitySet.Name);
}
Implementación de DAOs con Entity Framework
 Implementación del DAO genérico con Entity Framework
public void Create(E entity)
{
/* Adds the object to the object context. The entity's EntityState
* will be set to Added. Therefore, when SaveChanges is called, it
* will be clear to the Entity Framework that this entity needs to
* be inserted into the database.
*/
context.AddObject(GetQualifiedEntitySetName(entityClass.Name), entity);
/* Persists back to the database all of the changes made to
* the entities. By default, the SaveChanges method calls the method
* AcceptAllChanges after it has performed the database
* modifications. AcceptAllChanges pushes the current values of
* every attached entity into the original values and then changes
* their EntityState to Unchanged.
*/
context.SaveChanges();
}
Implementación de DAOs con Entity Framework
 Implementación del DAO genérico con Entity Framework
/// <exception cref="InstanceNotFoundException"/>
public E Find(PK id)
{
EntityKey entityKey = this.CreateEntityKey(id);
try
{
E result = (E)context.GetObjectByKey(entityKey);
return result;
}
catch (ObjectNotFoundException)
{
throw new InstanceNotFoundException(id, entityClass.FullName);
}
}
Implementación de DAOs con Entity Framework
 Implementación del DAO genérico con Entity Framework
public Boolean Exists(PK id)
{
Boolean objectFound = true;
EntityKey entityKey = this.CreateEntityKey(id);
try
{
object result = context.GetObjectByKey(entityKey);
}
catch (ObjectNotFoundException)
{
objectFound = false;
}
return objectFound;
}
Implementación de DAOs con Entity Framework
 Implementación del DAO genérico con Entity Framework
public E Update(E entity)
{
// Last Updates are sent to database
context.Refresh(RefreshMode.ClientWins, entity);
context.SaveChanges();
}
Implementación de DAOs con Entity Framework
 Implementación del DAO genérico con Entity Framework
/// <exception cref="InstanceNotFoundException"/>
public void Remove(PK id)
{
E objectToRemove = default(E);
try
{
// First we need to find the object
objectToRemove = Find(id);
context.DeleteObject(objectToRemove);
context.SaveChanges();
}
catch (InstanceNotFoundException)
{
throw;
}
Implementación de DAOs con Entity Framework
 Implementación del DAO genérico con Entity Framework
catch (OptimisticConcurrencyException)
{
context.Refresh(RefreshMode.ClientWins, objectToRemove);
context.DeleteObject(objectToRemove);
context.SaveChanges();
}
catch (InvalidOperationException)
{
throw new InstanceNotFoundException(id, entityClass.FullName);
}
}
Implementación de DAOs con Entity Framework
 Para implementar la persistencia utilizando Entity Framework, el DAO
necesita un objeto ObjectContext
Se asigna y recupera a través de la propiedad Context
 Se utilizará inyección de dependencias para establecer el valor de la propiedad Context

 Para implementar las operaciones se puede elegir EntitySQL o
Linq-to-Entities
Implementación de DAOs con Entity Framework
 Ej.: MiniBank > AccountDao
AccountDaoEntityFramework
public List<Account> FindByUserId(long userId, int startIndex,
int count)
{
ObjectSet<Account> accounts = Context.CreateObjectSet<Account>();
var result =
(from a in accounts
where a.usrId == userId
orderby a.accId
select a).Skip(startIndex).Take(count).ToList();
return result;
}
Implementación de DAOs con Entity Framework
 Ej.: MiniBank > AccountOperationDao
Bibliografía
 Recomendada:
 J. Lerman. Programming Entity Framework. 2nd
edition. O'Reilly. 2010.
Descargar