2009-09-18 4 views
6

Я использую Dynamic Linq Library/Sample из Microsoft, чтобы сделать заказ в списке. Так, например, у меня есть следующий C# код:Исключение нулевой ссылки в динамическом выражении LINQ

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

У меня есть случай, когда мой объект иметь 0: 1 отношения с другим объектом, который имеет свойство, которое может быть отображено в сетке. Когда мы пытаемся сортировать это, он отлично работает, пока все мои виджеты имеют этого ребенка. Например, мы заказываем Child.Name. Однако, когда Child имеет значение null, мы получаем исключение нулевой ссылки.

У меня есть некоторые опции здесь, которые я знаю, что я мог бы выбрать анонимный тип и привязать его к этому, я также мог бы выставить Child.Name на родительском объекте и обработать его с помощью кода (который мне не нравится, включая мой объектная модель для этого).

В идеальном мире я хотел бы обновить библиотеку для обработки этого случая. Прежде чем я погрузился в это, мне интересно, кто-то наткнулся на это или нет и уже имеет решение?

Редактировать

Похоже, я не объяснил достаточно хорошо. Я использую Dynamic Linq Library, который поставляется с C# samples. Эта библиотека добавляет некоторые полезные расширения, которые позволяют использовать строку InPlace из лямбда-выражения Так что мой код на самом деле что-то вроде этого:

private void BindGrid(sortField,sortDirection) 
{ 

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

Конечно строка там заменяется параметрами. Но это позволяет нам динамически изменять сортировку, когда пользователь нажимает на заголовок сетки. Нам не нужно, если тогда логика else обрабатывает все перестановки.

Мое решение, как я документирован ниже изменяет мой хороший чистый метод в:

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

И в то время как это работает, это означает теперь я должен обновлять этот код, как добавить новые поля или свойства, которые мы хотим выставить в сетке, которые находятся на дочернем объекте.

ответ

5

Если я вас правильно понял, я думаю, что вы хотите:

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

LINQ сможет генерировать SQL, который имитирует это выражение.

+1

Нет, это не то, о чем я говорю. Динамический linq является частью примера кода C# и позволяет использовать строку в качестве OrderBy, например. Он компилирует строку в выражение лямбда во время выполнения. – JoshBerke

+6

Почему этот ответ был принят в качестве фактического ответа? Я в той же ситуации. – Mike

2

На решение я нашел в моем случае не является идеальным снова будет обнаружить, когда выражение будет доступ к ребенку, чтобы изменить выражение сортировки быть

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

В идеале эта логика может быть запеченным в динамической библиотеке, я бы предпочел не изменять каждую сетку повсюду, чтобы обрабатывать все случаи, на которые это повлияет.

-2

Я не очень понимаю проблему (возможно, потому что это пятница вечер уже здесь ...), но вы не можете отсортировать список, как это:

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

где SortField является собственностью вы хочу сортировать. Это должно работать даже тогда, когда значение равно нулю ...

Извините, если это возможно, полностью рядом с точкой ...

+2

Вы полностью упустили точку. Поскольку ваш не единственный, я, должно быть, недостаточно объяснил себя. Я обновил вопрос, поэтому он довольно немного, но более ясен. – JoshBerke

1

Я была такая же проблема, но самое лучшее решение, которое я нашел в том, чтобы сделать ваш код немного более общий характер, изменив его в этом:

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

Не совершенным, не так, как вы получите доступ к Чайлдс из Чайлдс , но экономит ваше время от обновления вашего кода каждый раз, когда вы получаете нового родителя с нулевым значением.

Смежные вопросы