modo efficace per popolare interrogazione quadro Entify con oggetti correlati?

voti
0

Sto usando EF per un insieme di oggetti e vogliono interrogare un tipo di oggetto con le voci corrispondenti da altri due tavoli. Questo è quello di scaricare la query in un output XML. In un primo momento, utilizzato un join in quanto nei dati originali ogni dipendente sempre avuto 1+ istanze di un computer oggetto (soluzione # 2 di seguito), ma non è necessariamente vero.

Fini qui, immaginare:

  • un Dipendente oggetto,
  • ogni dipendente ha un EmployeeType (alcune voci fisso) e
  • Ogni dipendente ha a zero o più computer oggetti (in genere 0-3).
  • ogni computer appartiene a uno dei dipendenti, non tutti i dipendenti ha un computer.
  • ogni dipendente ha un criterio sul quale si basa la ricerca (come ad esempio Divisione ).

Così ho visto diverse soluzioni possibili:

  1. Utilizzare l'Employee.Computer.Load () all'interno di un ciclo, ma con 10.000 righe, che causa una riduzione delle prestazioni enorme.

  2. Utilizzare un join nella query, ma che lascia fuori tutti i dipendenti che non dispongono di un computer .

  3. Utilizzare LINQ to Entities, ma che sembra avere il sovraccarico di 1 #: durante il caricamento del computer è tutto colpisce il database per ogni dipendente .

  4. Utilizzare una seconda query (tutti Computer s con corrispondenti Computer.Employee.Division ), poi nel Employee ciclo, aggiungere qualsiasi computer per la data dei dipendenti. Mentre l'attuazione del presente, ho scoperto che solo in esecuzione la seconda query (con ToList () ) l'EF popola le corrette Employee.Computer liste con gli oggetti di cui ho bisogno.

Qui, # 4 carichi i dati con solo 2 banca dati colpisce invece di 10k +, e l'EntityFramework raccoglie in realtà gli oggetti e crea tutte le relazioni.

Le mie domande :

  • Con 4 #, è il fatto che l'EF popola l'Employee.Computer lista qualcosa su cui posso contare? Se è così, mi puoi indicare la documentazione?
  • C'è un modo migliore di 4 #?

UPDATE : Beh, bastardo. Ci dispiace, ma ho semplicemente rovinato tutto. Mi sono concentrato sul rapporto con la tabella Computer e perso il fatto che ho avuto un esplicito Employee.EmployeeTypeReference.Load () w / o prima prova per nulla, quindi la lista Computer è stato un non-problema completo.

Ho trovato solo questo durante l'esecuzione di alcuni test di performance e aggiungendo la soluzione di Craig per il mix. In realtà, i record non sono dipendenti e Computer, ma astrazioni, ed io (condizionalmente) comprendono ogni campo in output XML, ma sono piccoli: un nome, ID (PK) e ID (FK) più un INT sul tavolo Dipendente. Quindi, la mia presunzione è che la prestazione sarebbe simile dal momento che la EF creerebbe oggetti non molto più pesanti rispetto alla proiezione.

In ogni caso, ecco i risultati wher il tempo trascorso è stata la differenza prima di questa query e dopo l'XML risultante è stato creato.

  • Caso 1: come # 2, ma con include () dichiarazioni:

    list = ve.Employee.Include(Computer).Include(EmployeeType).Where(e => e.Division.ID == divId).OrderBy(e => e.Name);

    Trascorso: 4.96, 5.05

  • Caso 2: Usa in linea Load () :

    list = ve.Employee.Where(e => e.Division.ID == divId).OrderBy(e => e.Name);

    Trascorso: 74.62

  • Caso 3: come # 4, ma con include () dichiarazioni:

    list = from e in ve.Employee.Include(Computer).Include(EmployeeType) where e.Division.ID == divId orderby e.Name select e;

    Trascorso: 4.91, 5.47

  • Caso 4: Usa in linea Load () :

    list = from e in ve.Employee where e.Division.ID == divId orderby e.Name select e;

    Trascorso: 74.20

  • Caso 5: Usa * include ( EmployeeType) e query separata Computer, lasciare che EF associate:

    elist = ve.Employee.Include(EmployeeType).Where(te => te.Division.ID == divId).OrderBy(e => e.Name).ToList(); alist = ve.Alias.Where(a => a.Employee.Division.ID == divId).ToList();

    Trascorso: 4.50, 4.02

  • Caso 6: il suggerimento di Craig delle proiezioni:

    elist = from te in ve.ThesaurusEntry where te.Division.ID==divID orderby te.Name select new { ID = te.ID, Name = te.Name, Type = te.EmployeeType.Name, Freq = te.Frequency, Aliases = from a in te.Alias select new { ID = a.ID, Name = a.Name } };

    Trascorso: 0.73, 1.25

conclusioni

Load () è costoso, quindi uso include () o almeno prova con IsLoaded

La proiezione è un po 'noioso, ma significativamente più veloce di EF fix-up. [con questo test limitato sulle strette tavoli]

È pubblicato 26/08/2009 alle 23:16
fonte dall'utente
In altre lingue...                            


2 risposte

voti
2

Io credo che si può indicare che le relazioni possono essere pre-caricato

Dim employees = From emp in db.Employees.Include("Computer") _
                Select emp
Risposto il 27/08/2009 a 01:06
fonte dall'utente

voti
1

La soluzione di Rob lavorerà (+1), ma se non avete bisogno di tutti i campi a, diciamo, dei dipendenti e del computer, avrei fortemente consiglia proietta invece:

var q = from e in Context.Employees
        where e.Division.Id = divisionId
        select new
        {
            Name = e.Name,
            EmployeeType = e.EmployeeType.Description,
            ComputerIds = from c in e.Computers
                          select new 
                          {
                              Id = c.Id
                          }
        };

Qui si ottiene tutto ciò che serve in una query, ma niente di più : Tutti i campi non ti servono non saranno restituiti.

Si potrebbe probabilmente anche selezionare in XElements e basta salvare l'albero risultante, piuttosto che la conversione manualmente in XML. Non ho provato questo, ma sembra che dovrebbe funzionare.

Per quanto riguarda la # 4, sì, si può fare affidamento su questo, ma è sempre bene controllare IsLoadedprima di chiamare Load().

Risposto il 27/08/2009 a 14:17
fonte dall'utente

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more