代码之家  ›  专栏  ›  技术社区  ›  JoshBerke

动态Linq表达式中的空引用异常

  •  6
  • JoshBerke  · 技术社区  · 16 年前

    我正在使用Microsoft的动态Linq库/示例在列表上进行排序。例如,我有以下C代码:

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

    我有一个例子,我的对象与另一个对象有0:1的关系,这个对象的属性可能会显示在网格中。当我们尝试对它进行排序时,只要我所有的小部件都有这个孩子,它就可以正常工作。我们点的是 Child.Name 例如。但是,当child为空时,我们会得到空引用异常。

    我这里有一些选项,我知道我可以选择匿名类型并绑定到它,我还可以公开父对象上的child.name并通过代码处理它(我不喜欢为此包含我的对象模型)。

    在理想的情况下,我想更新库来处理这个案例。在我深入研究之前,我想知道是否有人遇到过这个问题,并且已经有了解决方案?

    编辑

    看来我解释得不够好。我正在使用 Dynamic Linq Library 它和 C# samples . 这个库添加了一些很好的扩展,使您可以在lambda表达式的位置使用字符串,因此我的代码实际上是这样的:

    private  void BindGrid(sortField,sortDirection)
    {
    
         this.grid.DataSource=....OrderBy("MyField ASC")....
    }
    

    当然,这里的字符串被参数替换了。但这允许我们在用户单击网格头时动态更改排序。我们不必非得用if-then-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();
    }
    

    当这项工作时,这意味着当我们添加新的字段或属性时,我必须更新这段代码,我们希望在子对象上的网格中公开这些字段或属性。

    4 回复  |  直到 13 年前
        1
  •  5
  •   teedyay    16 年前

    如果我正确理解你,我想你需要:

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

    Linq将能够生成模仿此表达式的SQL。

        2
  •  2
  •   JoshBerke    16 年前

    在解决方案中,我发现在我的例子中,不理想的是检测表达式何时要访问子级,将排序表达式更改为

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

    理想情况下,这个逻辑可以被烘焙到动态库中,我不想在整个地方修改每个网格来处理所有会受到影响的情况。

        3
  •  1
  •   Eduardo Wada    13 年前

    我也遇到过同样的问题,但我找到的最佳解决方案是通过将代码改为以下代码,使代码更加通用:

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

    不完美,不喜欢访问childs中的childs,但是每次您得到一个新的可以为空的childs时都可以避免更新您的代码。

        4
  •  -2
  •   RoelF    16 年前

    我不太明白这个问题(可能是因为已经是星期五晚上了…),但是你不能这样排序吗:

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

    其中SortField是要排序的属性。 即使该值为空,也应该可以执行此操作…

    对不起,如果这完全是离题的话…