5

Estoy trabajando en un proyecto que utiliza un primer modelo de código EF 4.2. Este modelo contiene una estructura de herencia TPH para productos. Necesito agrupar los resultados polimórficos de este modelo de herencia en el discriminador y me encuentro con algunos problemas.Tabla de Entity Framework 4.2 por grupo de jerarquía por discriminator

El marco de entidades no expone el discriminador para completar esta agrupación. Mi primera pregunta es ¿puedo obtener acceso directo a este discriminador? Mi lectura y experiencia me dicen que no, así que se me ocurrió esta solución que funciona de alguna manera. No está funcionando bien y no estoy contento con la forma en que tendrá que mantenerse.

Mis clases se ven algo como esto (simplificado):

Public MustInherit Class Product 
     <key()> 
     Public Property ProductID as integer 

     <StringLength(50, ErrorMessage:="Max 50 characters")> 
     <Required(ErrorMessage:="Product name is required")> 
     Public Property Name as String 

     <TimeStamp()> 
     Public Property Time_Stamp as DateTime = DateTime.Now() 
End Class 

Public Class Desktop 
     Inherits Product 

     <StringLength(50, ErrorMessage:="Max 50 characters")> 
     <Required(ErrorMessage:="Processor is required")> 
     Public Property Processor as String 
End Class 

Public Class Monitor 
     Inherits Product 

     <Required(ErrorMessage:="Monitor size is required")> 
     Public Property Size_Inches as Integer 
End Class 

me construyeron un método de extensión que tiene un producto y lo devuelve es BaseType nombre como una cadena.

<Extension()> 
Public Function ProductType(ByVal inProduct as Product) as String 
     ProductType = inProduct.GetType().BaseType.Name 
End Function 

Con eso, he construido esta estructura para agrupar los resultados de producto por tipo para que pueda funcionar a través de ellos:

Dim tmpProducts = db.Products.ToList() 
Dim GrpProducts = tmpProducts.GroupBy(Function(prod) prod.ProductType) _ 
          .Select(Function(s) New With {.ProductType = S.Key, 
                  .Products = S }) 

ahora puedo bucle a través de la lista para obtener el comportamiento que quiero, pero el rendimiento no es ideal y me preocupa que sea inaceptable a medida que crezca la cantidad de productos.

For Each ProductGroup in GrpProducts 
     Dim TypeName as String = ProductGroup.ProductType 
     Dim TypeProducts = ProductGroup.Products 
Next 

Además, esto me puede dar fácil acceso a las propiedades compartidas (Nombre), pero ahora no tengo muchas opciones para estos emitidos en su tipo de bienes, tal vez un caso de selección alrededor TypeName. . .

Cualquier recomendación es apreciada, también perdone cualquier error de código anterior, volví a escribir los ejemplos de memoria ya que no tengo acceso al proyecto en este momento.

Respuesta

2

Una solución sería modelar un poco más, y tener una nueva entidad ProductType que tenga una propiedad Name. Entonces tendría una relación simple 1-N entre Product y ProductType. No he usado EntityFramework, pero con NHibernate puede hacer fácilmente que el marco siempre se una a esa tabla en las consultas, para que no devuelva un proxy para ProductType por cada Product, lo que podría dañar el rendimiento.

Como complemento, en un futuro ProductType podría desarrollar otras propiedades interesantes (como los valores que son comunes para todos los Product de ese ProductType), por lo que añade flexibilidad a su solución, aunque tiene el costo inmediato de agregando otra tabla a su base de datos.

+0

Ésta es ciertamente una opción, aunque me siento propiedades comunes pertenecen a la definición de tipo cuando sea posible. Últimamente he estado agregando una propiedad sobresaliente de "ProductTypeName" a la clase base. Se siente anticuado y repite datos almacenados pero funciona mejor. – sgrade1979

1

siguiente consulta LINQ debe obtener una forma de resolver por grupo discriminador

from a in db.Records 
group a.ID by new 
{ 
    Name= a is Audio ? "Audio" : 
      a is Video ? "Video" : 
      a is Picture ? "Picture" : 
      a is Document ? "Document" : "File" 
} into g 
select new 
{ 
    Name = g.Key.Name, 
    Total = g.Count() 
} 
Cuestiones relacionadas