Professional Documents
Culture Documents
[editar]Informacin
general
Es un conjunto de APIs de acceso a datos para el Microsoft .NET Framework, apuntando a la versin de ADO.NET que se incluye con el .NET Framework 3.5. Fue lanzado como actualizacin separada junto con el Service Pack 1 para el .NET Framework, despus del lanzamiento de tanto el .NET Framework 3.5 y el Visual Studio 2008. Una nueva versin del Entity Framework (v 4.0) ser liberada junto al Visual Studio 2010 y el .NET Framework 4.0. Una entidad del Entity Framework es un objeto que tiene una clave representando la clave primaria de una entidad lgica de datastore. Un modelo conceptual Entity Data Model (modelo Entidad-Relacin) es mapeado a un modelo de esquema de datastore. Usando el Entity Data Model, el Framework permite que los datos sean tratados como entidades independientemente de sus representaciones del datastore subyacente. El Entity SQL es un lenguaje similar al SQL para consultar el Entity Data Model (en vez del datastore subyacente). Similarmente, las extensiones del Linq, Linq-to-Entities, proporcionan consultas tipeadas en el Entity Data Model. Las consultas Entity SQL y Linq-to-Entities son convertidas internamente en un Canonical Query Tree que entonces es convertido en una consulta comprensible al datastore subyacente (ej. en SQL en el caso de una base de datos relacional). Las entidades pueden utilizar sus relaciones, y sus cambios enviados de regreso al datastore.
[editar]Historia
La primera versin de Entity Framework (EFv1) fue incluida con .NET Framework 3.5 Service Pack 1 y Visual Studio 2008 Service Pack 1, realizada el 11 de agosto de 2008. Esta versin ha sido ampliamente criticada. La segunda versin de Entity Framework, llamada Entity Framework 4.0 (EFv4), fue realizada como parte de .NET 4.0 el 12 de abril de 2010 y se han abordado muchas de las crticas hechas a la versin 1.
Una tercera versin de Entity Framework, versin 4.1, se public el 12 de abril de 2011, con el apoyo de Code First. Una actualizacin de la versin 4.1 el nombre de Entity Framework 4.1 Update 1, se public el 25 de julio de 2011. Se incluye correcciones de errores y nuevos tipos soportados. La ltima versin es la 4.3.1, fue lanzada el 29 de febrero de 2012. Hay un par de actualizaciones, como es el soporte para la migracin.
Este es un muy buen artculo til para aquellos que tienen que decidir cual tipo de acceso a datos es ms conveniente utilizar segn los distintos escenarios.
http://msdn.microsoft.com/es-es/magazine/ee335715.aspx
A pesar de que Entidades simples normalmente no es el patrn preferido para las aplicaciones de N niveles, es la opcin ms viable en la primera versin de EF. Sin embargo, EF4 cambia significativamente las opciones para la programacin de N niveles con el marco. Algunas de las nuevas caractersticas clave incluyen lo siguiente: 1. Nuevos mtodos de marco que admiten operaciones desconectadas, como ChangeObjectState y ChangeRelationshipState, que cambian una entidad o una relacin a un estado nuevo (por ejemplo, agregado o modificado); ApplyOriginalValues, que permite definir los valores originales para una entidad y el nuevo evento ObjectMaterialized que se activa cada vez que el marco crea una entidad. 2. Compatibilidad con objetos CLR tradicionales (POCO) y valores de clave externa en las entidades. Estas caractersticas le permiten crear clases de entidad que se pueden compartir entre la implementacin del servicio de nivel intermedio y otros niveles, que probablemente no tengan la misma versin de Entity Framework (.NET 2.0 o Silverlight, por ejemplo). Los objetos POCO con claves externas tienen un formato de serializacin sencillo que simplifica la interoperabilidad con plataformas como Java. El uso de claves externas tambin permite un modelo de concurrencia mucho ms simple para las relaciones. 3. Plantillas T4 para personalizar la generacin de cdigo. Estas plantillas proporcionan una manera de generar clases que implementan los patrones DTO o Entidades de seguimiento automtico. El equipo de Entity Framework ha usado estas caractersticas para implementar el patrn Entidades de seguimiento automtico en una plantilla, con lo que ese patrn es mucho ms accesible, y a pesar de que los DTO siguen necesitando la mayor cantidad de trabajo durante la implementacin inicial, este proceso tambin es ms fcil con EF4. (La plantilla Entidades de seguimiento automtico y algunas otras caractersticas de EF estn disponibles como parte de una caracterstica de descarga web de Community Technology Preview (CTP) en lugar de estarlo en la caja de Visual Studio 2010/.NET 4. Los ejemplos que aparecen en este artculo suponen que tanto Visual Studio 2010/.NET 4 como la caracterstica CTP estn instalados). Con estas nuevas capacidades, una forma de evaluar los cuatro patrones que he descrito (Entidades simples, Conjunto de cambios, Entidades de seguimiento automtico y DTO) es en trminos de un equilibrio entre el valor de la arquitectura (separacin de preocupaciones/acoplamiento flexible, resistencia del contrato, formato eficiente de la conexin e interoperabilidad) y la facilidad de la implementacin y el tiempo de comercializacin. Si traza los cuatro patrones en un grfico que represente este equilibrio, es probable que el resultado se vea similar a la figura 1.
Figura 1 Comparacin de los patrones de N niveles con EF4 El patrn correcto para una situacin especfica depende de muchos factores. En general, los DTO proporcionan muchas ventajas de arquitectura con un alto costo inicial de implementacin. Conjunto de cambios exhibe pocas caractersticas de arquitectura buenas, pero es fcil de implementar (cuando est disponible para una tecnologa especfica, por ejemplo, el DataSet en el ADO.NET tradicional). Recomiendo un equilibrio pragmtico y gil entre estas preocupaciones al empezar con Entidades de seguimiento automtico y avanzando a los DTO si la situacin as lo garantiza. A menudo puede levantarse y ponerse en ejecucin rpidamente con Entidades de seguimiento automtico y seguir logrando muchos importantes objetivos de arquitectura. Este enfoque representa un equilibrio mucho mejor que Conjunto de cambios o Entidades simples, las que slo recomendara si no hubiese otras opciones viables. Por otro lado, los DTO son definitivamente la mejor opcin cuando la aplicacin se vuelve cada vez mayor y ms compleja, o en caso de que tenga requisitos que Entidades de seguimiento automtico no pueda satisfacer, como tasas distintas de cambio entre el cliente y el servidor. Estos dos patrones son las herramientas ms importantes que tiene en su cuadro de herramientas, por lo que vamos a darles un vistazo.
proyecto: una plantilla genera ObjectContext y la otra genera clases de entidad. Separar la generacin de cdigo en dos plantillas hace posible dividir el cdigo en ensamblados independientes, uno para las clases de entidad y otro para el contexto. La ventaja principal que tiene este enfoque es que puede tener sus clases de entidad en un ensamblado que no tenga dependencias en Entity Framework. De este modo y si lo desea, el nivel intermedio y el cliente pueden compartir el ensamblado de entidad (o al menos el cdigo que genera) y cualquier lgica de negocios que haya implementado. El contexto se mantiene en un ensamblado que tiene dependencias tanto en las entidades como en EF. Si el cliente del servicio est ejecutando .NET 4, simplemente puede hacer referencia al ensamblado de entidad desde el proyecto del cliente. Si el cliente ejecuta una versin anterior de .NET o Silverlight, es probable que desee agregar vnculos desde el proyecto del cliente a los archivos generados y volver a compilar el origen de la entidad en ese proyecto (teniendo como objetivo el CLR adecuado). Independiente de la manera en que estructura el proyecto, las dos plantillas trabajan en conjunto para implementar el patrn Entidades de seguimiento automtico. Las clases de entidad generadas son simples clases de POCO cuya nica caracterstica que va ms all del almacenamiento bsico de propiedades de entidad es llevar un registro de los cambios en las entidades, el estado general de una entidad, los cambios en propiedades crticas como tokens de concurrencia y cambios en las relaciones entre las entidades. Esta informacin de seguimiento adicional es parte de la definicin de DataContract para las entidades (para que cuando enva una entidad desde o hasta un servicio WCF, se transporte la informacin de seguimiento). En el cliente del servicio, se realiza un seguimiento automtico de los cambios en las entidades incluso si las entidades no estn conectadas a ningn contexto. Cada entidad generada tiene cdigo similar al siguiente para cada propiedad. Si cambia el valor de una propiedad en una entidad que tenga, por ejemplo, el estado Sin modificar, el estado cambia a Modificado: [DataMember] public string ContactName { get { return _contactName; } set { if (!Equals(_contactName, value)) { _contactName = value; OnPropertyChanged("ContactName"); } } } private string _contactName; De manera similar, si las entidades nuevas se agregan a un grfico o se eliminan entidades de un grfico, se registra esa informacin. Debido a que el estado de cada entidad se registra en la misma
entidad, el mecanismo de seguimiento se comporta como se podra esperar, incluso cuando relaciona entidades recuperadas desde ms de una llamada de servicio. Si establece una nueva relacin, slo se registra ese cambio; la entidad implicada mantiene el mismo estado, como si todas se hubiesen recuperado desde una sola llamada de servicio. La plantilla de contexto agrega un mtodo nuevo, ApplyChanges, al contexto generado. ApplyChanges adjunta un grfico de entidades al contexto y configura la informacin en el ObjectStateManager para coincidir con la informacin registrada en las entidades. Con la informacin que las entidades registran sobre ellas mismas y ApplyChanges, el cdigo generado administra tanto las preocupaciones de seguimiento de cambios como las de concurrencia, dos de las partes ms difciles de implementar correctamente una solucin de Nniveles. Como ejemplo concreto, la figura 2 muestra un ServiceContract simple que podra usar con Entidades de seguimiento automtico para crear un sistema de envo de pedidos de N niveles basado en la base de datos de ejemplo de Northwind. Figura 2 Un contrato de servicio simple para el patrn Entidades de seguimiento automtico [ServiceContract] public interface INorthwindSTEService { [OperationContract] IEnumerable<Product> GetProducts(); [OperationContract] Customer GetCustomer(string id); [OperationContract] bool SubmitOrder(Order order); [OperationContract] bool UpdateProduct(Product product); } El mtodo de servicio GetProducts se usa para recuperar datos de referencia en el cliente acerca del catlogo de productos. Normalmente esta informacin se almacena en la memoria cach de forma local y no se actualiza a menudo en el cliente. GetCustomer recupera un cliente y una lista de los pedidos de ese cliente. La implementacin de ese mtodo es muy simple, como aqu aparece: public Customer GetCustomer(string id) { using (var ctx = new NorthwindEntities()) { return ctx.Customers.Include("Orders") .Where(c => c.CustomerID == id) .SingleOrDefault();
} } Este es esencialmente el mismo cdigo que escribira para una implementacin de este tipo de mtodo con el patrn Entidades simples. La diferencia es que las entidades que se devuelven son de seguimiento automtico, lo que significa que el cdigo de cliente para usar estos mtodos tambin es muy simple, pero puede lograr mucho ms. Para ilustrarlo, supongamos que en el proceso de envo de pedidos no slo desea crear un pedido con lneas de detalles de pedidos adecuadas, sino que tambin actualizar partes de la entidad de cliente con la informacin de contacto ms reciente. Adems, desea eliminar cualquier pedido que tenga una OrderDate nula (quizs el sistema marca como rechazados los pedidos de esa manera). Con el patrn Entidades simples, la combinacin de agregar, modificar y eliminar entidades en un solo grfico requerira varias llamadas de servicio para cada tipo de operacin o una implementacin de servicio y contrato personalizado muy complicada si intentase implementar algo similar a Entidades de seguimiento automtico en la primera versin de EF. Con EF4, el cdigo de cliente podra verse como la figura 3. Figura 3 Cdigo de cliente para el patrn Entidades de seguimiento automtico var svc = new ChannelFactory<INorthwindSTEService>( "INorthwindSTEService") .CreateChannel(); var products = new List<Product>(svc.GetProducts()); var customer = svc.GetCustomer("ALFKI"); customer.ContactName = "Bill Gates"; foreach (var order in customer.Orders .Where(o => o.OrderDate == null).ToList()) { customer.Orders.Remove(order); } var newOrder = new Order(); newOrder.Order_Details.Add(new Order_Detail() { ProductID = products.Where(p => p.ProductName == "Chai") .Single().ProductID, Quantity = 1 }); customer.Orders.Add(newOrder); var success = svc.SubmitOrder(newOrder);
Este cdigo crea el servicio, llama a los dos primeros mtodos en l para obtener la lista de productos y una entidad de cliente y luego realiza cambios en el grfico de la entidad de cliente usando el mismo tipo de cdigo que podra escribir si estuviese creando una aplicacin de Entity Framework de dos niveles que se comunique directamente con la base de datos o si estuviese implementando un servicio en el nivel intermedio. (Si no est familiarizado con este estilo de creacin de un cliente de servicio WCF, crea automticamente un proxy de cliente sin crear servidores proxy para las entidades, porque estamos usando nuevamente las clases de entidad desde la plantilla Entidades de seguimiento automtico. Tambin podra usar el cliente generado por el comando Agregar referencia de servicio en Visual Studio si lo desea). Pero aqu no hay ObjectContext implicado. Slo est manipulando las entidades. Finalmente, el cliente llama al mtodo de servicio SubmitOrder para hacer subir los cambios al nivel intermedio. Por supuesto, en una aplicacin real los cambios que el cliente hace en el grfico probablemente vendran desde una interfaz de usuario de algn tipo y agregara control de excepciones en torno a las llamadas de servicio (es importante especialmente cuando tiene que comunicarse a travs de la red), pero el cdigo que aparece en la figura 3 ilustra los principios. Otro elemento importante que hay que observar es que cuando crea la entidad de detalle de pedido para el pedido nuevo, configura slo la propiedad ProductID en lugar de configurar la entidad Product misma. Esta es la nueva caracterstica de relacin de clave externa en accin. Reduce la cantidad de informacin que viaja a travs de la transmisin, porque slo serializa el ProductID de vuelta al nivel intermedio y no una copia de la entidad de producto. Es en la implementacin del mtodo de servicio SubmitOrder donde realmente se destaca Entidades de seguimiento automtico: public bool SubmitOrder(Order newOrder) { using (var ctx = new NorthwindEntities()) { ctx.Orders.ApplyChanges(newOrder); ValidateNewOrderSubmission(ctx, newOrder); return ctx.SaveChanges() > 0; } } La llamada a ApplyChanges realiza toda la magia. Lee la informacin de cambios desde las entidades y la aplica al contexto de manera tal que el resultado sea el mismo que si esos cambios se hubiesen realizado todo el tiempo en entidades adjuntas al contexto.
Este paso es muy importante porque, por s mismo, ApplyChanges empuja cualquier cambio que encuentra en un grfico completo de objetos relacionados al contexto. Nuestra expectativa de que el cliente slo agregar pedidos nuevos, actualizar al cliente, etc., no significa que un cliente con errores (o incluso malicioso) no hara nada ms. Qu pasa si cambiara el precio de un producto para hacer que un pedido sea ms barato o ms caro de lo que debiera ser? Los detalles sobre cmo se realiza la validacin son menos importantes que la regla crtica que establece que siempre debe validar los cambios antes de guardarlos en la base de datos. Esta regla se aplica independiente del patrn de N niveles que use. Un segundo principio de diseo crtico es que debe desarrollar mtodos de servicio especficos por separado para cada operacin. Sin estas operaciones por separado, no tiene un contrato seguro que represente lo que se permite y lo que no entre los dos niveles y la validacin adecuada de los cambios puede llegar a ser imposible. Si tena un solo mtodo de servicio SaveEntities en lugar de un mtodo SubmitOrder y UpdateProduct por separado (al que slo pueden obtener acceso usuarios autorizados para modificar el catlogo de productos), poda implementar fcilmente la parte de aplicar y guardar de ese mtodo, pero no podra validar de manera adecuada, porque no tendra manera de saber cundo se permiten las actualizaciones de productos y cuando no.
public class NewOrderDTO { public string CustomerID { get; set; } public string ContactName { get; set; } public byte[] CustomerVersion { get; set; } public List<NewOrderLine> Lines { get; set; } } public class NewOrderLine { public int ProductID { get; set; } public short Quantity { get; set; } } Est bien, en realidad son dos clases, una para el pedido y otra para las lneas de detalles de pedidos, pero el tamao de los datos se mantiene lo ms pequeo posible. La nica informacin aparentemente externa en el cdigo es el campo CustomerVersion, que contiene la informacin de versin de la fila que se usa para las comprobaciones de concurrencia en la entidad de cliente. Necesita esta informacin para la entidad de cliente, porque la entidad ya existe en la base de datos. Para el pedido y las lneas de detalles, son entidades nuevas que se envan a la base de datos, por lo que no se necesita su informacin de versin y el OrderID; las genera la base de datos cuando los cambios son persistentes. El mtodo de servicio que acepta este DTO usa las mismas API de Entity Framework de nivel inferior que la plantilla Entidades de seguimiento automtico usa para lograr sus tareas, pero ahora debe llamar a esas API directamente, en lugar de dejar que el cdigo generado las llame. La implementacin viene en dos partes. Primero, cree un grfico de entidades de cliente, pedido y detalle de pedido segn la informacin en el DTO (consulte la figura 4). Figura 4 Creacin de un grfico de entidades var customer = new Customer { CustomerID = newOrderDTO.CustomerID, ContactName = newOrderDTO.ContactName, Version = newOrderDTO.CustomerVersion, }; var order = new Order { Customer = customer, }; foreach (var line in newOrderDTO.Lines) { order.Order_Details.Add(new Order_Detail
{ ProductID = line.ProductID, Quantity = line.Quantity, }); } Luego adjunte el grfico al contexto y configure la informacin de estado adecuada: ctx.Customers.Attach(customer); var customerEntry = ctx.ObjectStateManager.GetObjectStateEntry(customer); customerEntry.SetModified(); customerEntry.SetModifiedProperty("ContactName"); ctx.ObjectStateManager.ChangeObjectState(order, EntityState.Added); foreach (var order_detail in order.Order_Details) { ctx.ObjectStateManager.ChangeObjectState(order_detail, EntityState.Added); } return ctx.SaveChanges() > 0; La primera lnea adjunta todo el grfico al contexto pero, cuando eso ocurre, cada entidad tiene el estado Sin modificar, por lo que primero indquele al ObjectStateManager que cambie el estado de la entidad de cliente a Modificado, pero slo con una propiedad, ContactName, marcada como modificada. Esto es importante porque en realidad no tiene toda la informacin de cliente, sino que slo la informacin que estaba en el DTO. Si marc todas las propiedades como modificadas, Entity Framework tratara de insistir en un buen nmero de valores nulos y ceros en otros campos de la entidad de cliente. A continuacin, cambie el estado del pedido y de cada uno de sus detalles de pedidos a Agregado y luego llame a SaveChanges. Dnde est el cdigo de validacin? En este caso, como tiene un DTO muy especfico para el escenario e interpreta ese objeto a medida que asigna la informacin desde l hacia sus entidades, realiza la validacin a medida que avanza. No hay manera de que este cdigo pudiera cambiar inadvertidamente el precio de un producto, porque nunca se toca la entidad de producto. Este es otro beneficio del patrn DTO, pero slo de manera indirecta. Todava tiene que realizar el trabajo de validacin: el patrn slo fuerza un nivel de validacin. En muchos casos, el cdigo necesita incluir la validacin adicional de los valores u otras reglas empresariales. Otra consideracin es la administracin adecuada de las excepciones de concurrencia. Como mencion anteriormente, la informacin de versin para la entidad de cliente est incluida en el DTO, por lo que est configurado para detectar adecuadamente los problemas de concurrencia si alguien ms modifica al mismo cliente. Un ejemplo ms completo asignara esta excepcin a un
error de WCF para que el cliente pudiera resolver el conflicto, o capturara la excepcin y aplicara algn tipo de directiva automtica para abordar el conflicto. Si deseaba ampliar el ejemplo agregando otra operacin, como la capacidad de modificar un pedido, podra crear otro DTO especficamente para ese escenario, con la informacin correcta justa para eso. Este objeto se vera similar a nuestro NewOrderDTO, pero tendra las propiedades OrderID y Version para las entidades de pedido y de detalles de pedido, as como tambin cada propiedad para la cual desea autorizar la autorizacin por parte de la llamada de servicio. La implementacin del mtodo de servicio tambin sera similar al mtodo SubmitOrderDTO que mostramos anteriormente, revisando los datos de DTO, creando objetos de entidad correspondientes y luego definiendo su estado en el administrador de estados antes de guardar los cambios en la base de datos. Si fuera a implementar el mtodo de actualizacin de pedidos con Entidades de seguimiento automtico y Objetos de transferencia de datos, encontrara que la implementacin de Entidades de seguimiento automtico vuelve a usar las entidades y comparte casi todo el mismo cdigo de implementacin de servicio con el nuevo mtodo de envo de pedidos; la nica diferencia sera el cdigo de validacin e incluso podra compartirse algo de eso. Sin embargo, la implementacin de DTO requiere una clase de Objeto de transferencia de datos por separado para cada uno de los dos mtodos de servicio y las implementaciones del mtodo siguen patrones similares, pero tienen muy poco cdigo, si lo hay, que se pueda compartir.
forma de excluirse de estas comprobaciones de concurrencia de relaciones. El resultado es que los servicios deben llevar los valores originales de las relaciones y configurarlos en el contexto antes de cambiar las relaciones. Sin embargo, con relaciones de clave externa, la relacin es simplemente una propiedad de la entidad, y si la entidad pasa su comprobacin de concurrencia, no se necesita una comprobacin adicional. Puede cambiar una relacin si simplemente cambia el valor de clave externa. Tenga cuidado con las colisiones de EntityKey cuando adjunte un grfico a un ObjectContext. Por ejemplo, si usa DTO y partes del grfico representan entidades agregadas recientemente para las que los valores clave de entidad no estn definidos, porque se generarn en la base de datos, debe llamar al mtodo AddObject para agregar el grfico completo de entidades y luego cambiar las entidades que no tengan estado Agregado al estado deseado, en lugar de llamar al mtodo Attach y luego cambiando las entidades Agregadas a ese estado. De lo contrario, cuando llama por primera vez a Attach, Entity Framework piensa que cada entidad debe tener el estado Sin modificar, lo que supone que los valores clave de entidad son finales. Si ms de una entidad de un tipo en especial tiene el mismo valor clave (por ejemplo, 0), Entity Framework arrojar una excepcin. Si comienza con una entidad con estado Agregada, evita este problema porque el marco no espera que las entidades Agregadas tengan valores clave nicos. Desactive la carga diferida automtica (otra caracterstica nueva de EF4) cuando se devuelvan entidades desde los mtodos de servicio. Si no lo hace, el serializador activar la carga diferida y tratar de recuperar entidades adicionales desde la base de datos, lo que har que se devuelvan ms datos de los deseados (si las entidades estn completamente conectadas, podra serializar toda la base de datos) o, lo que es ms probable, recibir un error porque se eliminar el contexto antes de que el serializador trate de recuperar los datos. Entidades de seguimiento automtico no tiene activada la carga diferida de manera predeterminada, pero si crea una solucin DTO es algo que tiene que vigilar.
Y al final
La versin .NET 4 de Entity Framework hace que la creacin de aplicaciones de N niveles slidas en su arquitectura sea mucho ms fcil. Para la mayora de las aplicaciones, recomiendo comenzar con la plantilla Entidades de seguimiento automtico, que simplifica el proceso y permite volver a usar la mayor parte. Si tiene diferentes tasas de cambio entre el servicio y el cliente o si necesita tener el control absoluto del formato de la conexin, debe moverse a una implementacin de Objetos de transferencia de datos. Independiente del patrn que elija, siempre tenga en cuenta los principios clave que representan los patrones y antipatrones y nunca olvide validar los datos antes de guardar. Daniel Simmons es arquitecto miembro del equipo de Entity Framework en Microsoft.