2009-09-18 14 views
6

Sto utilizzando la libreria/campione Dynamic Linq di Microsoft per eseguire l'ordine in un elenco. Così, per esempio, ho il seguente codice C#:Eccezione di riferimento null in un'espressione LINQ dinamica

myGrid.DataSource=repository.GetWidgetList() 
     .OrderBy(sortField + " " + sortDirection).ToList(); 

ho un caso in cui il mio oggetto ha un 0: 1 rapporto con un altro oggetto, che ha una proprietà che può essere visualizzato nella griglia. Quando proviamo a ordinare questo, funziona bene fino a quando tutti i miei Widget hanno questo figlio. Ad esempio, stiamo ordinando tramite Child.Name. Tuttavia, quando Child è null, otteniamo l'eccezione di riferimento null.

Ho alcune opzioni qui che so che potrei selezionare in un tipo anonimo e collegarlo, potrei anche esporre il Child.Name sull'oggetto genitore e gestirlo via codice (che non mi piace comprendendo il mio modello oggetto per questo).

In un mondo ideale mi piacerebbe aggiornare la libreria per gestire questo caso. Prima di immergermi in questo, mi chiedo se qualcuno lo abbia imbattuto o no e abbia già una soluzione?

Modifica

Sembra che non ho spiegato abbastanza bene. Sto usando lo Dynamic Linq Library fornito con lo C# samples. Questa libreria aggiunge alcune belle estensioni che consentono di utilizzare una serie di inplace un'espressione lambda Quindi il mio codice è in realtà qualcosa di simile:

private void BindGrid(sortField,sortDirection) 
{ 

    this.grid.DataSource=....OrderBy("MyField ASC").... 
} 

Naturalmente la stringa non viene sostituito con i parametri. Ma questo ci consente di modificare l'ordinamento in modo dinamico mentre l'utente fa clic su un'intestazione di griglia. Non dobbiamo, se non altro, la logica per gestire tutte le permutazioni.

La mia soluzione come ho documentato muggito cambia il mio bel metodo pulito in:

private void BindGrid() 
{ 
    var sortField=this._sortField; 
    if (sortField=="Child.Name") 
    { 
     sortField="iif(Child==null,null,Child.Name)"; 
    } 
    this.grid.DataSource=repository.GetWidgetList() 
            .OrderBy(sortField + " " + this._sortDirection) 
            .ToList(); 
} 

E mentre questo funziona, questo ora significa che devo aggiornare il codice come aggiungiamo nuovi campi o proprietà che vogliamo esporre nella griglia che si trovano su un oggetto figlio.

risposta

5

Se ho capito bene, penso che si desidera che questo:

repository.GetParentObjects() 
    .OrderBy(p => p.Child == null ? "" : p.Child.Name); 

LINQ sarà in grado di generare SQL che riproduce questa espressione.

+1

No, questo non è quello a cui mi riferisco. Linq dinamico fa parte del codice di esempio C# e consente di utilizzare una stringa come OrderBy, ad esempio. Compila la stringa con un'espressione lambda in fase di esecuzione. – JoshBerke

+6

Perché questa risposta è stata accettata come risposta effettiva? Sono nella stessa situazione. – Mike

2

Sulla soluzione che ho trovato che nel mio caso non è l'ideale di nuovo sarebbe quello di rilevare quando l'espressione sta per accedere al bambino, di modificare l'espressione di ordinamento per essere

iif(Child == null,null,Child.Name) ASC 

Idealmente questa logica può essere infornato nella libreria dinamica, preferirei non dover modificare ogni griglia su tutto il luogo per gestire tutti i casi che questo avrà un impatto.

-2

Io non capisco il problema (forse perché è venerdì sera già qui ...), ma non posso ordinare l'elenco come questo:

myGrid.DataSource=repository.GetWidgetList() 
    .OrderBy(w => w.SortField).ToList(); 

dove SortField è la proprietà che si voglio ordinare. Questo dovrebbe funzionare anche quando il valore è nullo ...

scusate se è forse tutto questo il punto ...

+2

Hai completamente perso il punto. Dal momento che il tuo non è l'unico, non devo spiegarmi abbastanza bene. Ho aggiornato la domanda quindi è probabilmente un po 'più chiara. – JoshBerke

1

Ho avuto lo stesso problema, ma la soluzione migliore che ho trovato è stato quello di rendere il codice un po 'più generica, modificando in questo modo:

private void BindGrid() 
{ 
    var sortField = this._sortField; 
    var splitted_sortField = this._sortField.Split(new char[]{'.'}, StringSplitOptions.RemoveEmptyEntries); 
    if (splitted_sortField.Length > 1) 
    { 
     sortField = "iif("+splitted_sortField[0]+"==null,null,"+sortField+")"; 
    } 
    this.grid.DataSource = repository.GetWidgetList() 
            .OrderBy(sortField + " " + this._sortDirection) 
            .ToList(); 
} 

Non è perfetto, non piace dare accesso al bambino di Childs , ma ti salva dall'aggiornare il tuo codice ogni volta che ottieni un nuovo figlio nullable.

Problemi correlati