Caricamento lento se la raccolta contiene voci

2

Spesso vedo classi di modelli con proprietà come questa:

public IList<Note> Notes { get; set; }
public bool HasNotes { get; set; }

Dove l'elenco è inizializzato pigro, ma la proprietà booleana viene caricata direttamente. Questo ha il vantaggio, che viene caricato solo il conteggio, quando la raccolta non è necessaria, ma l'avvertenza è che il valore per la proprietà booleana viene sempre calcolato.

Questo mi ha fatto riflettere e ho trovato una soluzione come questa:

public IList<Note> Notes { get; set; }
public bool HasNotes
{
  get
  {
    if (Notes != null) return Notes.Any();
    else // calculate (e.g. sql exists)
  }
}

In questo modo il calcolo si verifica solo se la raccolta non viene caricata.

Questo sarebbe un buon approccio? Esistono già delle migliori pratiche sconosciute?

    
posta Philipp M 18.06.2013 - 13:07
fonte

2 risposte

3

Non puoi mai sapere come gli utenti prevedono di utilizzare il tuo codice. Nella tua proposta, se un chiamante cerca prima HasNotes e solo più tardi Notes , avrai anche una chiamata SQL troppe: prima il COUNT e poi l'intero SELECT per popolare Notes .

Se sai che gli utenti non chiameranno mai HasNotes prima di Notes , allora la tua implementazione ha senso, ma in tal caso, ti suggerirei di andare fino in fondo in quella direzione.

Ad esempio, invece di cercare di essere intelligenti sulle query indovinando i modelli di utilizzo in un modello, è possibile creare un livello di accesso ai dati esplicito che esegua esattamente le query giuste necessarie e compila le classi del modello. Le classi modello vengono quindi ridotte a semplici classi di data holder. Potrebbero contenere la logica di dominio e la logica di convalida e tutto ciò, ma certamente nessuna conoscenza del DB.

Questo è davvero il dibattito ORM vs DAO. Fowler ha una breve discussione di questo dibattito qui .

In generale, sceglierei un approccio chiaro:

  1. Cerca di essere il più intelligente possibile nelle classi di modelli. Questo è il modo NHibernate. Produce un livello di modello di facile utilizzo che genera solo alcune query troppe. In tal caso, lascia la roba intelligente su NHibernate e non cercare di ottimizzare le classi del tuo modello prematuramente.
  2. Non provi nemmeno a essere intelligente, ma lasciala all'utente per chiamare i giusti metodi che popolano il modello.

Sento che l'approccio che suggerisci è da qualche parte nel mezzo ("È un'ottimizzazione, ma solo se chiami le cose così e così"). Questo confonderà gli altri sviluppatori e te stesso in pochi mesi. Meglio prendere una posizione chiara.

    
risposta data 18.06.2013 - 13:34
fonte
0

Would this be a good approach?

Penso che un approccio migliore sarebbe quello di caricare sempre HasNotes insieme al resto dell'entità. In questo modo, la proprietà è fondamentalmente gratuita (un'altra colonna restituita dovrebbe essere molto più economica rispetto alla creazione di un'altra query SQL per ogni entità).

    
risposta data 18.06.2013 - 15:36
fonte

Leggi altre domande sui tag