【问题标题】:What's wrong with this linq query?这个 linq 查询有什么问题?
【发布时间】:2009-05-07 15:52:53
【问题描述】:

我确定这确实很愚蠢,但我只是没有看到它..

pData.LocationHours 的类型为 BaseLocationHoursDataSet.LocationHoursDataTable。然而,当我将光标悬停在l 上时,我看到的只是“(range variable) TSource l”——这是为什么呢?为什么 linq 不知道它在处理什么?我用不同的 DataTable 尝试同样的事情,一切正常......不是这个人。可能是什么问题?

protected ListItem[] GetHoursTypesListItems(BaseLocationHoursDataSet pData)
{
  return (
            from l in pData.LocationHours   // putting cursor over the l here shows:  (range variable) TSource l
            select new ListItem
            {
              Value = l,  //ignore the fact that I didn't specify a property - that's the problem, that none of the properties of the object show up.
              Text = l
            }
          ).ToArray<ListItem>();
}

.

更新:

问题是它不知道 l 是什么。我没有向我显示正确的类型(我希望看到 LocationHoursRow),而是看到“TSource l”.. 那是什么?为什么它不知道“from l in pData.LocationHours”行中的 l 是什么?

【问题讨论】:

    标签: c# .net asp.net linq


    【解决方案1】:

    我看到“TSource l”.. 那是什么?

    首先,编译器将查询从查询​​形式转换为方法调用形式。这个查询变成了

    pData.LocationHours.Select(l=>new ... )
    

    其次,编译器尝试确定“pData.LocationHours.Select”的含义。如果 pData.LocationHours 的类型没有 Select 方法,则编译器开始寻找扩展方法。大概是找到了扩展方法

    IEnumerable<TResult> Select<TSource, TResult>(
      this IEnumerable<TSource> source, Func<TSource, TResult> projection)
    

    或者它可能会找到相同的 IQueryable 版本。

    现在编译器说“但是类型参数 TSource 和 TResult 是什么?”

    我不知道您的问题是什么,但问题很可能发生在此阶段。由于某种原因,类型推理引擎无法确定 TSource 是什么。

    现在您将鼠标悬停在“l”上。发生什么了?智能感知引擎询问语义分析器“l”的类型是什么。语义分析器报告说,“l”已知是函数中的参数,该函数接受 TSource 并返回 TResult,但方法类型推断器无法确定 TSource 对应的实际类型。

    因此,智能感知引擎尽其所能,并告诉您 l 是 TSource 类型。智能感知引擎还指出“l”是查询的范围变量,并告诉您这一事实。

    为什么 难道它不知道我在“来自 l 在 pData.LocationHours" 行?

    我不知道,但很明显 某些东西 在您的代码中被破坏了。在不知道所有表达式的类型以及确切可用的扩展方法的情况下,我很难说出到底出了什么可怕的错误。

    当代码损坏无法编译时,intellisense 仍然尽其所能。我同意在这种情况下,结果有点令人困惑,但至少你知道在出现问题之前它已经达到了类型推断。

    【讨论】:

    • 我喜欢你的解释 - +1。而且我确实同意有些东西坏了——我得出结论,这与我正在使用的 DataTable 的实施方式有关。我并不为此感到自豪,但我在 AsEnumerable() 的帮助下解决了这个问题,而不是弄清楚那个 DataTable 是怎么回事(我必须跳过很多政治圈来更新/修复)。
    【解决方案2】:

    我想你可能需要 l.Field:

    select new ListItem
    {
       Value = l.Field,
       Text = l.Field2
    }
    

    好的,这样的事情怎么样: 由于您使用的是数据集,因此您的查询可能需要类似于以下内容:

    var query = pData.Tables["Name"].AsEnumerable()
    

    然后对查询对象执行 LINQ

    此外,发现此代码 sn-p 可能会有所帮助。它正在使用通用数据集作为参考。

    DataSet ds = new DataSet();
    FillOrders(ds);
    
    DataTable orders = ds.Tables["SalesOrderHeader"];
    
    var ordersQuery = orders.ToQueryable();
    
    var query = from o in ordersQuery
    where o.Field<bool>("OnlineOrderFlag") == true
    select new { SalesOrderID = o.Field<int>("SalesOrderID"),
    OrderDate = o.Field<DateTime>("OrderDate") };
    

    【讨论】:

    • 是的,但是当我输入“l”时,没有显示任何属性。因为它不知道 l 是什么。
    • 我添加了一些额外的 cmets,看看这是否有助于引导您走向正确的方向
    • 谢谢! AsEnumerable() 成功了。然后我只需要为其中的每个属性的引用转换 l。
    • 太棒了!我很高兴能帮上忙
    【解决方案3】:

    'l' 不代表 LocationHours 表中的数据行吗?我认为您需要在 lambda 中指定“l”的属性。

    【讨论】:

      【解决方案4】:

      应该是 Value = l.Value 还是类似的东西?

      【讨论】:

        猜你喜欢
        • 2012-07-08
        • 1970-01-01
        • 1970-01-01
        • 2011-09-29
        • 2011-10-13
        相关资源
        最近更新 更多