5

Sto lavorando su un progetto utilizzando un codice EF 4.2 primo modello. Questo modello contiene una struttura di ereditarietà TPH per i prodotti. Ho bisogno di raggruppare i risultati polimorfici di questo modello di ereditarietà sul discriminatore e sto correndo su alcuni problemi.Entity Framework 4.2 tabella per gruppo gerarchico per discriminatore

L'entità quadro non espone il discriminatore per completare questo raggruppamento. La mia prima domanda è: posso avere accesso diretto a questo discriminatore? La mia lettura e la mia esperienza mi stanno dicendo di no, quindi ho trovato questa soluzione in un certo senso. Non sta funzionando bene e non sono contento di come dovrà essere mantenuto.

Le mie lezioni aspetto qualcosa di simile (semplificato):

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 

ho costruito un metodo di estensione che richiede un prodotto e lo restituisce è BaseType nome come stringa.

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

Con questo, ho costruito questa struttura per raggruppare i risultati del prodotto per tipo in modo da poter correre attraverso di loro:

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

ora posso scorrere la lista per ottenere il comportamento che voglio, ma le prestazioni non sono ideali e sono preoccupato che sarà inaccettabile con il crescere del numero di prodotti.

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

Inoltre, questo mi può dare un facile accesso alle proprietà condivise (nome), ma ora non ho molte opzioni per lanciare questi nelle loro tipo reale, forse un caso di selezione intorno TypeName. . .

Eventuali raccomandazioni sono apprezzate, per favore perdonare eventuali errori di codice sopra, ho ridigitato gli esempi dalla memoria in quanto non ho accesso al progetto al momento.

risposta

2

Una soluzione sarebbe quella di modellare un po 'di più e avere una nuova entità ProductType con una proprietà Name. Quindi avresti una semplice relazione 1-N tra Product e ProductType. Non ho usato EntityFramework, ma con NHibernate si potrebbe facilmente fare in modo che il framework entri sempre in quella tabella sulle query, in modo che non restituisca un proxy per ProductType per ogni Product, che potrebbe danneggiare le prestazioni.

Come un add-on, in futuro ProductType potrebbe sviluppare altre interessanti proprietà (ad esempio, i valori che sono comuni per ogni Product di quella ProductType), in modo che aumenta la flessibilità di una soluzione, anche se ha il costo immediato di aggiungendo un'altra tabella al tuo database.

+0

Questo è certamente un'opzione, anche se mi sento proprietà comuni appartengono alla definizione del tipo, quando possibile. Ultimamente ho aggiunto una proprietà "ProductTypeName" sovrascrivibile alla classe base. Sente cludgy e ripete i dati memorizzati ma ha prestazioni migliori. – sgrade1979

1

seguente query LINQ dovrebbe farti un modo per risolvere gruppo dal discriminatore

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() 
}