Capitulo 6 - ADO.NET Entity Framework (Parte 3)

Actualizando el esquema de base de datos

Si se realizan cambios en el modelo conceptual, se tendrá que actualizar el esquema de base de datos para que coincida con el modelo. Para actualizar la base de datos, clic secundario en el diseñador de Entity Framework y elegir Generar bases de datos desde modelo. Generar la base de datos Asistente produce un archivo de comandos SQL que se puede editar y ejecutar.

El Generador de EntityObject


Al leer la base de datos para generar las entidades, es posible que se desee un mayor control sobre las entidades que se generan. Se pueden crear y editar plantillas mediante el uso de plantillas de Transformación texto (T4) para la Generación de código.

Para utilizar el Generador de EntityObject de ADO.NET, se debe hacer clic derecho en la superficie del diseñador de Entity Framework à clic en Add Code Generation Item.

clip_image001[1]

La siguiente pantalla es una advertencia de seguridad que indica que la ejecución de la plantilla de T4 puede causar daño a su equipo. Al hacer clic en Aceptar, la plantilla de T4para ejecutar y crear entidades que se pueden personalizar.

Cosas para tener en cuenta sobre el uso de la plantilla Generador de EntityObject:

·       El nombre del archivo de plantilla determina el nombre del archivo de código que genera. Por ejemplo, si la plantilla de texto se llama TextTemplate.tt, el archivo generado será TextTemplate.vb o TextTemplate.cs.

·       El .Edmx debe estar vacío.

·       La inicialización SourceCsdlPath a continuación se debe establecer la ruta relativa de acceso de los .Edmx o archivos .Csdl .

Después de agregar el generador de ADO.NET EntityObject, el archivo de Visual Basic o C # archivo que normalmente existe en el EDMX: El archivo esta casi vacío, excepto por una nota que indica que la generación de código por defecto está desactivada. Ahora, se puede modificar el Generador de EntityObject plantilla de texto, y la generación de código que se produce a partir del contenido de la plantilla.

Generador “Self-Tracking Entity” (de entidades con seguimiento propio)

Este elemento de plantilla genera dos archivos .tt (plantilla de texto): <nombre de modelo>.tt y <nombre de modelo>.Context.tt. El archivo <nombre de modelo>.tt genera los tipos de entidad y una clase auxiliar que contiene la lógica del seguimiento de cambios que utilizan las entidades con seguimiento propio y los métodos de extensión que permiten establecer el estado de las entidades de seguimiento propio.  El archivo <nombre de 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.

Se usan las entidades de seguimiento propio cuando trabaja con aplicaciones de n capas.

Los siguientes métodos de extensión se pueden llamar en las entidades de seguimiento propio:

·       Método StartTracking: Indica a la herramienta de seguimiento de cambios de la entidad que comience a registrar todos los cambios aplicados a la entidad. Esto incluye los cambios en las propiedades escalares, las recopilaciones y las referencias a otras entidades. Las entidades de seguimiento propio inician el seguimiento de forma automática cuando se deserializan en el cliente a través de Windows Communication Foundation (WCF). El seguimiento también se activa para las entidades creadas recientemente en los siguientes escenarios:

o   Se crea una relación entre la nueva entidad y una entidad que ya está realizando el seguimiento de los cambios.

o   Se llama al método MarkAs[State] o al método AcceptChanges en una entidad.

·       Método StopTracking :Detiene los registros de cambios.

·       Métodos MarkAs: Activan el seguimiento. Estos métodos de extensión facilitan los cambios de estado de una entidad de forma explícita a Added, Modified, Deleted yUnchanged.

·       Los métodos MarkAs[State] devuelven la misma entidad a la que se aplican, con el estado modificado. En el siguiente ejemplo se modifica el estado de la entidad a Unchanged:

department.Course = new Course { CourseID = courseID }.MarkAsUnchanged();

·       AcceptChanges : Borra la información de seguimiento de cambios de una entidad y cambia su estado a Unchanged. Si desea restablecer el estado de una relación, se debe llamar a AcceptChanges en las dos entidades que participen en la relación.

Consideraciones al trabajar con entidades de seguimiento propio

·      Debemos asegurarnos de que el proyecto cliente tenga una referencia al ensamblado con los tipos de entidad. Si agrega solo la referencia de servicio al proyecto cliente, este proyecto usará los tipos de proxy WCF y no los tipos reales de entidad de seguimiento propio.

·       Las llamadas a la operación de servicio no deben tener estado y deben crear una nueva instancia del contexto del objeto. Asimismo, se recomienda que se cree el contexto del objeto en un bloque using.

·       Si se envía el gráfico modificado en el cliente al servicio y, a continuación, planea seguir trabajando con el mismo gráfico en el cliente, debe iterar manualmente el gráfico y llamar al método AcceptChanges de cada objeto para restablecer la herramienta de seguimiento de cambios. Si los objetos del gráfico contienen propiedades con valores generados por la base de datos (por ejemplo, valores de identidad o simultaneidad), Entity Framework reemplazará los valores de estas propiedades por los valores generados por la base de datos después de llamar al método SaveChanges.

·       Cuando se cambia la relación entre objetos mediante el establecimiento de la propiedad de clave externa, la propiedad de navegación de referencia se establece en NULL y no se sincroniza con la entidad de seguridad adecuada en el cliente. Después de adjuntar el gráfico al contexto del objeto (por ejemplo, después de llamar al método ApplyChanges), se sincronizan las propiedades de clave externa y de navegación.
Las entidades con seguimiento propio no están habilitadas para realizar una carga diferida.

·       El código generado en la plantilla del Generador de entidades de seguimiento propio ADO.NET no admite la serialización binaria ni la serialización en objetos, pero se puede personalizar la plantilla para agregar la compatibilidad de serialización binaria. Uso de la serialización binaria y ViewState con entidades de seguimiento propio.

 

Entidades POCO

“POCO” Plain Old CLR objets, significa que se pueden utilizar las clases que creamos con Entity Framework, siempre y cuando los nombres de los tipos de entidad, tipos complejos, y las propiedades de las clases de datos personalizadas coincidan con los nombres de los tipos de entidad, tipos complejos y propiedades en el modelo conceptual. Esto permite utilizar los objetos de dominio con el modelo de datos.

Cuando el Entity Framework fue lanzado por primera vez (. NET 3.5 SP1), tenia muchas restricciones. Las clases de entidad tenían que ser subclases de EntityObject (IPOCO). Estas interfaces incluyen IEntityWithKey, IEntityWithChangeTrackery IEntityWithRelationships. Con Entity Framework 4.0 ya no se necesita heredar de una clase base o implementación de interfaces para conseguir la persistencia, tampoco los metadatos o atributos de asignación de los miembros de tipo.

Por ejemplo las clases:

-------------------------------------VB-------------------------------------------

Public Class Customer

Public Property CustomerID As String

Public Property CompanyName As String

Public Property ContactName As String

Public Property ContactTitle As String

Public Property Address As String

Public Property City As String

Public Property Region As String

Public Property PostalCode As String

Public Property Country As String

Public Property Phone As String

Public Property Fax As String

Public Property Orders() As List(Of Order)

End Class

Public Class Order

Public Property OrderID As Integer

Public Property CustomerID As String

Public Property EmployeeID As Nullable(Of Integer)

Public Property OrderDate As Nullable(Of DateTime)

Public Property RequiredDate As Nullable(Of DateTime)

Public Property ShippedDate As Nullable(Of DateTime)

Public Property ShipVia As Nullable(Of Integer)

Public Property Freight As Nullable(Of Decimal)

Public Property ShipName As String

Public Property ShipAddress As String

Public Property ShipCity As String

Public Property ShipRegion As String

Public Property ShipPostalCode As String

Public Property ShipCountry As String

Public Property Customer As Customer

End Class

-------------------------------------CS-------------------------------------------

public class Customer

{

public string CustomerID { get; set; }

public string CompanyName { get; set; }

public string ContactName { get; set; }

public string ContactTitle { get; set; }

public string Address { get; set; }

public string City { get; set; }

public string Region { get; set; }

public string PostalCode { get; set; }

public string Country { get; set; }

public string Phone { get; set; }

public string Fax { get; set; }

public List<Order> Orders { get; set; }

}

public class Order

{

public int OrderID { get; set; }

public string CustomerID { get; set; }

public int? EmployeeID { get; set; }

public DateTime? OrderDate { get; set; }

public DateTime? RequiredDate { get; set; }

public DateTime? ShippedDate { get; set; }

public int? ShipVia { get; set; }

public decimal? Freight { get; set; }

public string ShipName { get; set; }

public string ShipAddress { get; set; }

public string ShipCity { get; set; }

public string ShipRegion { get; set; }

public string ShipPostalCode { get; set; }

public string ShipCountry { get; set; }

public Customer Customer { get; set; }

}

Comenzando con las entidades POCO

Cuando se inicia el Asistente para Entity Data Model,  pide que seleccionemos Generar desde la base de datos o desde modelo vacío. En este ejemplo, vamos a generar a partir de la base de datos está seleccionada. Seleccionamos una conexión con la base de datos Northwind y el nombre de la configuración de conexiónNorthwindPocoEntities. Elegimos los objetos de base de datos,(en este ej las tablas Clientes y Pedidos) y se debe configurar nombre del modelo NorthwindPocoModel.

clip_image002

En el archivo de EDMX, en la ventana Propiedades, debe borrar la propiedad Custom Tool para desactivar la generación automática de clases. NET para el modelo conceptual,Añadir las clases Customer y Order a este proyecto y crear una clase ObjectContext (NorthwindPocoContext).

-------------------------------------VB-------------------------------------------

Imports System.Data.Objects

Public Class NorthwindPocoContext

Inherits ObjectContext

Public Sub New()

MyBase.New("name= NorthwindPocoEntities", "NorthwindPocoEntities")

Me._customers = MyBase.CreateObjectSet(Of Customer)()

Me._orders = MyBase.CreateObjectSet(Of Order)()

End Sub




Public ReadOnly Property Customers As ObjectSet(Of Customer)

Get

Return Me._customers

End Get

End Property

Private _customers As ObjectSet(Of Customer)

Public ReadOnly Property Orders As ObjectSet(Of Order)

Get

Return Me._orders

End Get

End Property

Private _orders As ObjectSet(Of Order)

End Class

-------------------------------------CS-------------------------------------------

public class NorthwindPocoContext : ObjectContext

{

public NorthwindPocoContext()

: base("name=NorthwindPocoEntities", "NorthwindPocoEntities")

{

_customers = CreateObjectSet<Customer>();

_orders = CreateObjectSet<Order>();

}

public ObjectSet<Customer> Customers

{

get

{

return _customers;

}

}

private ObjectSet<Customer> _customers;

public ObjectSet<Order> Orders

{

get

{

return _orders;

}

}

private ObjectSet<Order> _orders;

}

Otras consideraciones sobre POCO

·       En lugar de crear manualmente las clases POCO, se puede configurar una plantilla de textoT4 para generar las clases POCO.

·       Los getters y setters de una clase POCO pueden tener cualquier modificador de acceso (público, privado), pero ninguna de las propiedades asignadas pueden ser overrideable (virtual en C # ), y no se puede ser de confianza parcial.

·       Cualquier tipo de colección que implemente la interfaz ICollection puede ser utilizado como un conjunto al crear tipos POCO. Si no se inicializa una colección cuando se instancia una clase POCO que tiene una colección, se crea una lista genérica .

 

Funciones definidas por el modelo

Una función definida por el modelo es una función que se define en un modelo conceptual para proporcionar funcionalidad adicional dentro de su consultas de LINQ to Entity.

La definición para una función definida por el modelo contiene la información siguiente:

·       El nombre de la función. (Necesario)

·       El tipo del valor devuelto. (Opcional)

Para agregar una función definida por el modelo, se debe abrir el archivo EDMX con un editor de XML, en este caso, es el NorthwindModel.edmx, este se mostrara como XML.

Se debe buscar la etiqueta ConceptualModels que es una etiqueta de esquema. Dentro de esa etiqueta se debe agregar el modelo de funciones definidas:

por ejemplo el detalle de las ordenes (DetailTotal):

<Function Name="DetailTotal" ReturnType="Decimal">

<Parameter Name="od" Type="NorthwindModel.Order_Detail" />

<DefiningExpression>

(od.UnitPrice * od.Quantity) * CAST(1 - od.Discount AS DECIMAL)

</DefiningExpression>

</Function>

Esta función devuelve un valor decimal, acepta un parámetro, od, que es de tipo NorthwindMode.Order_Detail. La etiqueta contiene DefiningExpression. En esta expresión, la función CAST (SQL), se llevará a cabo del lado del servidor. Cierre y guarde el archivo EDMX.

Para conectar el código recién creado  con nuestras clases, se debe agregar una función en Visual Basic o C # , que tendrá que ser anotada con el atributo EdmFunctionAttribute. Esta función puede ser otro método dela propia clase, pero la mejor práctica es crear una clase separada y definir este método como shared (C # static).

-------------------------------------VB-------------------------------------------

Public Class ModelDefinedFunctions

<EdmFunction("NorthwindModel", "DetailTotal")>

Public Shared Function DetailTotal(ByVal orderDetail As Order_Detail) As Decimal

Throw New NotSupportedException( _

"DetailTotal can only be used in a LINQ to Entities query")

End Function

End Class

-------------------------------------CS-------------------------------------------

public class ModelDefinedFunctions

{

[EdmFunction("NorthwindModel", "DetailTotal")]

public static decimal DetailTotal(Order_Detail orderDetail)

{

throw new NotSupportedException(

"DetailTotal can only be used in a LINQ to Entities query");

}

}

La función definida por el modelo se puede utilizar en una consulta LINQ to Entities, y se ejecutará en el servidor.Por ejemplo:

-------------------------------------VB-------------------------------------------

Dim db As New NorthwindEntities()

gv.DataSource = (From od In db.Order_Details

Where od.Order.CustomerID = "ALFKI"

Select New With

{

od.OrderID,

od.ProductID,

od.Quantity,

od.Discount,

od.UnitPrice,

.DetailTotal = ModelDefinedFunctions.DetailTotal(od)

}).ToList()

-------------------------------------CS-------------------------------------------

var db = new NorthwindEntities();

gv.DataSource = (from od in db.Order_Details

where od.Order.CustomerID == "ALFKI"

select new

{

od.OrderID,

od.ProductID,

od.Quantity,

od.Discount,

od.UnitPrice,

DetailTotal = ModelDefinedFunctions.DetailTotal(od)

}).ToList();

 

Resumen de la lección

·       La capa de servicios de objetos convierte LINQ to Entities y algunas consultas ESQL a un árbol de comandos SQL.

·       El proveedor de EntityClient se encarga de la correspondencia entre el modelo conceptual y el modelo de almacenamiento para crear un árbol de comandos ADO.NET.

·       ADO.NET es la tecnología usada para comunicarse con la base de datos.

·       Se puede usar el modelo Code First para crear el modelo conceptual y luego crear la base de datos a partir de esto.

·       Se puede implementar el modelo Database First para generar el modelo conceptual a partir de una base de datos existente.

·       El ObjectContext es el principal objeto que se usa para ejecutar las consultas y actualizar la base de datos.

·       Lazy loading (carga perezosa) no carga los datos de los objetos hasta que se los referencie.

·       Eager loading  (carga ansiosa) usa el método de extensión Include para cargar los datos de la tabla hija, cuando la tabla principal se está cargando.

·       Explicit loading (carga explicita) usa el método de extensión Load para cargar los datos de la tabla hija antes de utilizarlos.

·       Entity Framework soporta el mapeo de tipos complejos y procedimientos almacenados.

·       Entity Framework admite la herencia de las tablas por jerarquía de clases (TPH) y las tablas por tipo (TPT).

·       Entity Framework admite la herencia de  tabla por clase concreta (TPC) , pero el
Diseñador de Entity Framework no lo soporta.

·       Se puede modificar el modelo conceptual y enviar los cambios a la base de datos.
Visual Studio. NET proporciona generador T4 de plantilla de EntityObject  por el cual se puede controlar la generación de entidades.

·       Visual Studio. NET también ofrece la plantilla T4 SelfTracking mediante la cual se pueden crear y controlar el seguimiento de las entidades.

·       El Entity Framework soporta la creación de Plain Old CLR objets (POCO) que pueden ser rastreados.

·       El Entity Framework permite crear funciones definidas por el modelo por el cual se pueden crear en el servidor funciones que se pueden llamar desde dentro de una consulta LINQ.

 

No hay comentarios:

Publicar un comentario