2009-09-18 9 views
6

Estoy utilizando la biblioteca/muestra de Dynamic Linq de Microsoft para hacer un pedido en una lista. Así, por ejemplo, tengo el siguiente código C#:Excepción de referencia nula en una expresión de LINQ dinámico

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

tengo un caso en el que mi objeto tiene un 0: 1 relación con otro objeto, que tiene una propiedad que se manifiesten en la red. Cuando intentamos ordenar esto, funciona bien siempre y cuando todos mis widgets tengan este elemento secundario. Estamos ordenando por Child.Name por ejemplo. Sin embargo, cuando Child es nulo, obtenemos la excepción de referencia nula.

Tengo algunas opciones aquí que sé que podría seleccionar en un tipo anónimo y vincular a eso, también podría exponer Child.Name en el objeto principal y manejar esto a través de código (que no me gusta comprender mi modelo de objeto para esto).

En un mundo ideal, me gustaría actualizar la biblioteca para manejar este caso. Antes de sumergirme en él, me pregunto si alguien se ha topado con esto o no y ya tiene una solución.

Editar

Parece que no me explico lo suficientemente bien. Estoy usando el Dynamic Linq Library que viene con el C# samples. Esta biblioteca añade algunas extensiones agradables que le permiten utilizar una serie de in-situ una expresión lambda Así que mi código es en realidad algo como esto:

private void BindGrid(sortField,sortDirection) 
{ 

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

Por supuesto que la cadena no se sustituye con los parámetros. Pero esto nos permite cambiar la clasificación de forma dinámica a medida que el usuario hace clic en un encabezado de la grilla. No tenemos que hacerlo si no es lógico para manejar todas las permutaciones.

Mi solución como he documentado abajo cambia mi buen método limpio en:

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

Y si bien esto funciona, esto ahora significa que tengo que actualizar el código a medida que añadimos nuevos campos o propiedades que queremos exponer en la grilla que se encuentran en un objeto secundario.

Respuesta

5

Si he entendido bien, creo que quieres esto:

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

LINQ podrá generar SQL que imita esta expresión.

+1

No, esto no es a lo que me refiero. El linq dinámico es parte del código de muestra C# y le permite usar una cadena como OrderBy, por ejemplo. Compila la cadena a una expresión lambda en tiempo de ejecución. – JoshBerke

+6

¿Por qué se aceptó esta respuesta como la respuesta real? Estoy en la misma situación. – Mike

2

En solución que he encontrado que en mi caso no es lo ideal sería una vez más para detectar cuando la expresión se va a acceder el niño, para cambiar la expresión de ordenación para ser

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

Lo ideal sería que esta lógica puede Al horno en la biblioteca dinámica, prefiero no tener que modificar cada cuadrícula en todo el lugar para manejar todos los casos que esto afecte.

-2

yo no entiendo muy bien el problema (tal vez porque es viernes por la noche aquí ya ...), pero no puedo ordenar la lista de la siguiente manera:

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

donde SortField es la propiedad que quiero ordenar Esto debería funcionar incluso cuando el valor es nulo ...

Lo siento si es tal vez completamente fuera de lugar ...

+2

Completamente se perdió el punto. Como no eres el único, no debo haberme explicado lo suficiente. Actualicé la pregunta por lo que probally es un poco pero más claro. – JoshBerke

1

he tenido el mismo problema, pero la mejor solución que encontré fue que el código quede un poco más genérica cambiándola por esto:

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

No es perfecto, no le va a gustar dar acceso a niño de niño , pero te ahorra actualizar tu código cada vez que obtienes un nuevo hijo que admite nulos.

Cuestiones relacionadas