【问题标题】:Null Reference Exception in a Dynamic LINQ Expression动态 LINQ 表达式中的空引用异常
【发布时间】:2009-09-18 14:18:50
【问题描述】:

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

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

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

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

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

编辑

看来我解释得不够清楚。我正在使用C# samples 附带的Dynamic Linq Library。这个库添加了一些不错的扩展,让您可以使用字符串代替 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();
}

虽然这可行,但现在这意味着我必须更新此代码,因为我们要在子对象上的网格中添加要在网格中公开的新字段或属性。

【问题讨论】:

    标签: c# linq dynamic-linq


    【解决方案1】:

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

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

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

    【讨论】:

    • 不,这不是我所指的。动态 linq 是 C# 示例代码的一部分,例如,您可以将字符串用作 OrderBy。它在运行时将字符串编译为 lambda 表达式。
    • 为什么这个答案被接受为实际答案?我也有同样的情况。
    【解决方案2】:

    我发现在我的情况下再次不理想的解决方案是检测表达式何时访问子项,将排序表达式更改为

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

    理想情况下,这个逻辑可以嵌入到动态库中,我宁愿不必到处修改每个网格来处理这将影响的所有情况。

    【讨论】:

      【解决方案3】:

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

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

      不完美,不喜欢访问孩子的孩子,但每次你得到一个新的可为空的孩子时,你不必更新你的代码。

      【讨论】:

        【解决方案4】:

        我不太明白这个问题(可能是因为这里已经是星期五晚上了...),但你不能像这样对列表进行排序:

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

        其中 SortField 是您要排序的属性。 即使值为空,这也应该有效......

        对不起,如果这可能完全题外话......

        【讨论】:

        • 你完全没有抓住重点。既然你不是唯一的,我一定没有很好地解释自己。我更新了这个问题,所以它可能有点但更清楚了。
        猜你喜欢
        • 2019-11-07
        • 2012-09-29
        • 1970-01-01
        • 2011-11-22
        • 1970-01-01
        • 2021-07-18
        • 2011-01-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多