2009-09-18 5 views
6

J'utilise la bibliothèque/échantillon Dynamic Linq de Microsoft pour faire une commande sur une liste. Ainsi, par exemple, j'ai le code C#:Exception de référence nulle dans une expression LINQ dynamique

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

j'ai un cas où mon objet a un 0: 1 relation avec un autre objet, qui a une propriété qui pourrait être affiché dans la grille. Quand nous essayons de trier ça, ça fonctionne bien tant que tous mes Widgets ont cet enfant. Nous commandons par Child.Name par exemple. Lorsque Child est null, cependant, nous obtenons l'exception de référence nulle.

J'ai quelques options ici que je sais que je pourrais choisir dans un type anonyme et lier à cela, je pourrais également exposer le Child.Name sur l'objet parent et manipuler ceci par l'intermédiaire du code (que je n'aime pas modèle d'objet pour cela).

Dans un monde idéal, je voudrais mettre à jour la bibliothèque pour gérer ce cas. Avant de m'y plonger, je me demande si quelqu'un a déjà traversé ça ou pas et a déjà une solution?

Modifier

On dirait que je n'ai pas expliqué assez bien. J'utilise le Dynamic Linq Library qui vient avec le C# samples. Cette bibliothèque ajoute quelques belles extensions qui vous permettent d'utiliser une chaîne INPLACE d'une expression lambda donc mon code est en fait quelque chose comme ceci:

private void BindGrid(sortField,sortDirection) 
{ 

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

Bien sûr, la chaîne, il est remplacé par les paramètres. Mais cela nous permet de changer le tri dynamiquement lorsque l'utilisateur clique sur un en-tête de grille. Nous n'avons pas d'autre logique pour gérer toutes les permutations.

Ma solution que j'ai décrit ci-dessous change ma belle méthode propre dans:

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

Et tout cela fonctionne, cela signifie maintenant que je dois mettre à jour ce code que nous ajoutons de nouveaux champs ou des propriétés que nous voulons exposer dans la grille qui sont sur un objet enfant.

Répondre

5

Si je vous comprends bien, je pense que vous voulez ceci:

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

LINQ sera capable de générer du code SQL qui imite cette expression.

+1

Non, ce n'est pas ce dont je parle. Le linq dynamique fait partie de l'exemple de code C# et vous permet d'utiliser une chaîne en tant que OrderBy par exemple. Il compile la chaîne à une expression lambda lors de l'exécution. – JoshBerke

+6

Pourquoi cette réponse a-t-elle été acceptée comme réponse? Je suis dans la même situation. – Mike

2

sur la solution que j'ai trouvé dans mon cas n'est pas idéal serait de nouveau à détecter le moment où l'expression va accéder à l'enfant, de changer l'expression de tri pour être

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

Idéalement cette logique peut être cuit dans la bibliothèque dynamique, je préfère ne pas avoir à modifier chaque grille partout pour gérer tous les cas, cela aura un impact.

-2

Je ne comprends pas vraiment le problème (peut-être parce qu'il est ici vendredi soir déjà ...), mais ne peux pas vous trier la liste comme ceci:

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

où SortField est la propriété que vous vouloir trier. Cela devrait fonctionner même lorsque la valeur est nulle ...

Désolé si elle est peut-être complètement à côté du point ...

+2

Vous avez complètement manqué le point. Puisque vous n'êtes pas le seul, je n'ai pas dû m'expliquer assez bien. J'ai mis à jour la question pour qu'elle soit un peu plus probante mais plus claire. – JoshBerke

1

J'ai eu le même problème, mais la meilleure solution que j'ai trouvé était de rendre votre code un peu plus générique en changeant dans ceci:

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

Pas parfait, ne vous donnera accès à de Childs Childs , mais vous évite de mettre à jour votre code chaque fois que vous obtenez un nouvel enfant Nullable.

Questions connexes