2009-09-18 12 views
6

Używam biblioteki dynamicznej Linq/próbki firmy Microsoft do zamawiania na liście. Tak na przykład mam następujący kod C#:Wyjątek odwołania zerowego w dynamicznym wyrażeniu LINQ

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

Mam przypadek gdzie mój przedmiot posiada 0: 1 związek z innym obiektem, który posiada właściwości, które mogą być wyświetlane w siatce. Kiedy próbujemy to sortować, działa dobrze, o ile wszystkie moje widżety mają to dziecko. Zamawiamy na przykład przez Child.Name. Jednak gdy wartość Child ma wartość null, otrzymamy wyjątek odwołania do wartości zerowej.

Mam kilka opcji, o których wiem, że mogłem wybrać anonimowy typ i powiązać z tym, mogę również wystawiać Child.Name na obiekcie nadrzędnym i obsługiwać to za pomocą kodu (Którego nie lubię obejmującego moje model obiektowy dla tego).

W idealnym świecie chciałbym zaktualizować bibliotekę do obsługi tej sprawy. Zanim zagłębię się w to, zastanawiam się, czy ktoś już to przebiegł czy nie i czy ma już rozwiązanie?

Edit

Wygląda na to, że nie wyjaśnił dostatecznie dobrze. Używam Dynamic Linq Library dostarczanego z C# samples. Biblioteka ta dodaje kilka ciekawych rozszerzeń, które pozwalają korzystać z inplace ciąg wyrażenia lambda Więc mój kod jest faktycznie coś takiego:

private void BindGrid(sortField,sortDirection) 
{ 

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

Oczywiście łańcuch nie otrzymuje z parametrami. Ale to pozwala nam dynamicznie zmieniać sortowanie, gdy użytkownik kliknie nagłówek siatki. Nie musimy, jeśli nie logika innego, obsłużyć wszystkie permutacje.

Moje rozwiązanie jak udokumentowane mieszek zmienia moje ładne czyste metodę w:

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

A gdy to działa, teraz oznacza to muszę aktualizować ten kod jak dodać nowe pola lub właściwości, które chcemy eksponować w siatce znajdującej się na obiekcie podrzędnym.

Odpowiedz

5

Jeśli rozumiem zostanie poprawnie, myślę, że chcesz to:

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

LINQ będzie w stanie wygenerować SQL, który naśladuje to wyrażenie.

+1

Nie, to nie jest to, co mam na myśli. Dynamiczny linq jest częścią przykładowego kodu C# i pozwala na przykład użyć łańcucha jako OrderBy. Kompiluje ciąg do wyrażenia lambda w czasie wykonywania. – JoshBerke

+6

Dlaczego ta odpowiedź została przyjęta jako faktyczna odpowiedź? Jestem w tej samej sytuacji. – Mike

2

ROZWIĄZANIE Znalazłem co w moim przypadku nie jest idealny znowu byłoby wykryć gdy wyrażenie ma dostęp do dziecka, aby zmienić wyrażenie sortowania być

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

Idealnie ta logika może być upieczonym w dynamicznej bibliotece, wolałbym nie modyfikować każdej siatki w każdym miejscu, aby obsłużyć wszystkie przypadki, które będą miały wpływ.

-2

ja naprawdę nie rozumiem problemu (może dlatego, że jest tu już piątek wieczorem ...), ale nie można posortować listę tak:

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

gdzie SortField jest własnością ty chcesz się posortować. to powinno działać nawet wtedy, gdy wartość jest null ...

Niestety, czy to może całkowicie mija się z celem ...

+2

Całkowicie przegapiłeś ten punkt. Ponieważ nie tylko ja nie wytłumaczyłem się wystarczająco dobrze. Zaktualizowałem to pytanie, więc jest to trochę prawdopodobne, ale wyraźniejsze. – JoshBerke

1

miałem ten sam problem, ale najlepszym rozwiązaniem znalazłem aby Twój kod trochę bardziej ogólne, zmieniając go w ten sposób:

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

Nie idealne, nie będzie jak dać dostęp do Childs Childs , ale oszczędza ci aktualizacji kodu za każdym razem, gdy otrzymasz nowe, nullable dziecko.

Powiązane problemy