primary name framework foreign dataannotations data column annotation c# .net entity-framework .net-4.0

name - key data annotation c#



Entity Framework Complex Type vs Crear nueva entidad (3)

Estoy leyendo sobre Entity Framework 4.0 y me preguntaba por qué debería crear un tipo complejo y no una nueva Entidad (Tabla) y una relación entre ellos.


Basado en los conceptos de diseño controlados por dominio, la raíz agregada podría tener uno o más objetos internos como sus partes. En este caso, los objetos internos, dentro del límite de la raíz agregada, no tienen ninguna LLAVE. La clave principal se aplicará a ellos o de alguna manera así. Su respuesta vuelve al beneficio de mantener todas las Partes dentro de la raíz Agregada que hacen que su modelo sea más robusto y mucho más simple.


El ejemplo perfecto es una dirección. Usar un tipo complejo para una dirección es mucho más fácil de manejar que una nueva entidad. Con los tipos complejos no tiene que tratar con la clave principal. Piense en acceder a una dirección cuántos tipos comunes de entidades tendrían una dirección (Unidades de negocio, Personas, Lugares). Imagínese rellenando las direcciones de muchas personas y necesitando establecer una clave para cada una. Con los tipos complejos, simplemente acceda a las propiedades internas de su tipo y listo. Aquí hay un enlace de MSDN de un ejemplo. http://msdn.microsoft.com/en-us/library/bb738613.aspx


Esta pregunta ya lleva un tiempo aquí, pero voy a agregar una respuesta de todos modos con la esperanza de que el próximo pobre sollozo sepa lo que le espera.

Los tipos complejos no admiten la carga diferida, al menos no en EF 4.3. Tomemos como ejemplo la situación de la dirección. Tiene una tabla de persona con 15 columnas, 5 de las cuales contienen información de dirección para ciertas personas. Tiene 50k registros. Se crea la entidad Person para la tabla con una dirección de tipo complejo.

Si necesita una lista de nombres de todos los individuos en su base de datos, lo haría

var records = context.Persons;

que también incluye direcciones, bombeando valores 5 * 50k en su lista sin motivo y con un retraso notable. Puede optar por cargar solo los valores que necesita en un tipo anónimo con

var records = from p in context.Persons select new { LastName = p.LastName, FirstName = p.FirstName, }

que funciona bien para este caso, pero si necesita una lista más completa con, por ejemplo, 8 columnas sin dirección, deberá agregar cada una de forma anónima o simplemente ir con el primer caso y volver a cargar la dirección inútil datos.

Esto es lo que pasa con los tipos anónimos: aunque son muy útiles dentro de un solo método, lo obligan a usar variables dinámicas en otras partes de su clase o clase de niños, lo que niega algunas de las instalaciones de refactorización de Visual Studio y lo deja abierto a errores de tiempo de ejecución. Lo ideal es que usted circule entidades entre sus métodos, por lo que esas entidades deben llevar el menor equipaje posible. Esta es la razón por la carga perezosa es tan importante.

Cuando se trata del ejemplo anterior, la información de la dirección debería estar realmente en una tabla propia con una entidad completa que la cubra. Como beneficio adicional, si su cliente solicita una segunda dirección para una persona, puede agregarla a su modelo simplemente agregando una referencia de dirección adicional en Persona.

Si, a diferencia del ejemplo anterior, realmente necesita los datos de dirección en casi todas las consultas que realiza y realmente desea tener esos campos en la tabla Persona, simplemente agréguelos a la entidad Persona. Ya no tendrá el prefijo de dirección limpio, pero no es exactamente algo por lo que perder el sueño.

¡Pero espera hay mas!

Los tipos complejos son un caso especial, un bache en el suave paisaje de las entidades EF simples. Es posible que los proyectos de su proyecto no sean elegibles para heredar de la clase base de su entidad, por lo que es imposible pasarlos por métodos que traten con sus entidades en general.

Supongamos que tiene una clase base de entidad denominada EntityModel que define un ID de propiedad. Esta es la clave para todos sus objetos de entidad, por lo que ahora puede crear

class EntityModelComparer<T> : IEqualityComparer<T> where T : EntityModel

que luego puede usar con Distinct () para filtrar duplicados de cualquier IQueryable de tipo T donde T es una clase de entidad. Un tipo complejo no puede heredar de EntityModel porque no tiene una propiedad de ID, pero eso está bien porque de todos modos no estaría usando distintas características.

Más abajo en la línea te encuentras con una situación en la que necesitas alguna forma de pasar por cualquier entidad y realizar una operación. Tal vez desee enumerar dinámicamente las propiedades de una entidad en la interfaz de usuario y permitir que el usuario realice consultas en ellas. Así que creas una clase que puedes instanciar para un tipo particular y haz que se encargue de todo:

public class GenericModelFilter<T> : where T : EntityModel

Oh, espera, tu tipo complejo no es del tipo EntityModel. Ahora tiene que complicar el árbol de herencia de su entidad para acomodar tipos complejos o deshacerse del contrato de EntityModel y reducir la visibilidad.

Avanzando, agrega un método a su clase que basado en las selecciones de usuario puede crear una expresión que puede usar con linq para filtrar cualquier clase de entidad

Expression<Func<T, bool>> GetPredicate() { ... }

Así que ahora puedes hacer algo como esto:

personFilter = new GenericModelFilter<Person>(); companyFilter = new GenericModelFilter<Company>(); addressFilter = new GenericModelFilter<Address>(); //Complex type for Person ... var query = from p in context.Persons.Where(personFilter.GetPredicate()) join c in context.Companies.Where(companyFilter.GetPredicate()) on p.CompanyID = c.ID select p;

Esto funciona de la misma manera para todos los objetos de entidad ... excepto Dirección con sus necesidades especiales. No puedes hacer una unión como lo hiciste con la Compañía. Puedes navegar hasta ella desde Persona, pero ¿cómo aplicas esa Expresión en ella y aún así terminas con Persona al final? Ahora debe tomar un momento y descubrir este caso especial para un sistema simple que funciona fácilmente en cualquier otro lugar.

Este patrón se repite a lo largo de la vida útil de un proyecto. ¿Hablo por experiencia? Desearía no haberlo hecho. Los tipos complejos siguen deteniendo tu progreso, como un estudiante mal portado al final de la clase, sin agregar nada de esencia. Hazte un favor y opta por objetos de entidad reales en su lugar.