2013-04-26 8 views
5

Ho due tabelle nel mio database: TPM_AREAS e TPM_WORKGROUPS. Esiste una relazione molti-a-molti tra queste due tabelle e queste relazioni sono memorizzate in una tabella denominata TPM_AREAWORKGROUPS. Questa tabella è simile al seguente:C'è un modo rapido per ottenere ogni associazione tra due entità?

enter image description here

Che cosa devo fare è caricare tutti questi mapping in memoria in una sola volta, nel modo più veloce possibile. Come TPM_AREAWORKGROUPS è un associazione, non posso solo dire:

var foo = (from aw in context.TPM_AREAWORKGROUPS select aw); 

Mi vengono in mente tre modi per farlo forse questo, però io non sono molto sicuro come eseguire ognuno di loro, né quale sia il migliore.

1) del carico in ogni gruppo di lavoro, comprese le aree associate:

qualcosa di simile:

var allWG = (from w in context.TPM_WORKGROUPS.Include("TPM_AREAS") 
      where w.TPM_AREAS.Count > 0 
      select w); 
// Loop through this enumeration and manually build a mapping of distinct AREAID/WORKGROUPID combinations. 

Pro: Questo è probabilmente il modo EntityFramework standard di fare le cose, e non richiede a cambiare qualsiasi struttura o mappatura del database.

Contro: Potrebbe essere potenzialmente lento, poiché la tabella TPM_WORKGROUPS è piuttosto grande e la tabella TPM_AREAWORKGROUPS ha solo 13 righe. Inoltre, non esiste la classe TPM_AREAWORKGROUPS, quindi dovrei restituire una raccolta di tuple o creare una nuova classe per questo.

2) cambiare il mio modello

Idealmente, vorrei una classe TPM_AREAWORKGROUP, e una proprietà context.TPM_AREAWORKGROUP. Ho usato il designer per creare questo modello direttamente dal database, quindi non sono abbastanza sicuro su come forzare l'associazione come un modello reale. C'è un modo semplice per farlo?

Pro: Mi consente di selezionare direttamente su questa tabella, eseguita in una riga di codice. Sìì!

Contro: Mi costringe a cambiare il mio modello, ma questa è una brutta cosa?

3) Avvitarlo, utilizzare l'SQL raw per ottenere ciò che voglio.

Posso ottenere la proprietà StoreConnection del contesto e chiamare direttamente CreateCommand(). Posso quindi solo fare:

using (DbCommand cmd = conn.CreateCommand()) 
{ 
    cmd.CommandText = "SELECT AreaId, WorkgroupId FROM TPM_AREAWORKGROUPS"; 
    var reader = cmd.ExecuteReader(); 
    // Loop through and get each mapping 
} 

Pro: Veloce, facile, non richiede me per cambiare il mio modello.

Contro: Sembra una specie di hacky. Ovunque nel progetto, stiamo usando solo il codice standard di Entity Framework, quindi questo devia dalla norma. Inoltre, ha gli stessi problemi della prima opzione; non esiste ancora la classe TPM_AREAWORKGROUPS.

Domanda: Qual è la soluzione migliore per questo problema?

Idealmente, mi piacerebbe fare # 2 ma non sono abbastanza sicuro come regolare il mio modello. O forse qualcuno sa di un modo migliore delle mie tre opzioni.

risposta

3

si potrebbe fare:

var result = context 
    .TPM_WORKGROUPS 
    .SelectMany(z => z.TPM_AREAS.Select(z2 => new 
        { 
         z2.AREAID, 
         z.WORKGROUPID 
        })); 

Lo SQL tradotto sarà un semplice SELECT AREAID, WORKGROUPID FROM TPM_AREAWORKGROUPS.

su altre opzioni:

  • non vorrei utilizzare l'opzione 3) perché ho personalmente evito SQL prime il più possibile quando si utilizza Entity Framework (vedi https://stackoverflow.com/a/8880157/870604 per alcuni motivi).

  • Non vorrei usare l'opzione 2) perché dovresti cambiare il modello, e c'è un modo semplice ed efficace che consente di modificare .

+0

Ah, questa è una grande implementazione della prima opzione. Penso che questo finirà per essere la risposta accettata .. –

+0

@MikeChristensen Ho modificato la risposta per fornire alcuni commenti su altre 2 opzioni. Vorrei davvero utilizzare LINQ per le entità con il tuo modello attuale qui. – ken2k

0

Che ne pensi di utilizzare la proiezione per caricare i dati?

Si potrebbe fare che riempire un oggetto inanimato e quindi lavorare con esso nel modo desiderato.

+0

Esempio di codice per favore? –

Problemi correlati