【问题标题】:InvalidOperationException in LINQPad query against SQLite database针对 SQLite 数据库的 LINQPad 查询中的 InvalidOperationException
【发布时间】:2012-07-12 02:06:25
【问题描述】:

我在应用程序中有以下 LINQ 查询。数据源是在内存中构建的List<Borehole>,用于测试目的。

var lq = from p in data
         group p by p.CostCenter into g
         select new {  CostCenter = g.Key, 
                       AverageDepth = g.Average(p => p.OriginalDepth),
                       NullDepthCount = g.Count(p => p.OriginalDepth == null) };

它运行完美,并给出了所需的选择结果。但是,当我在 LINQPad 中运行以下查询时,它会导致 InvalidOperationException:

var lq = from p in Boreholes
          group p by p.CostCenter into g
          select new {  CostCenter = g.Key, 
                        AverageDepth = g.Average(p => p.OriginalDepth),
                        NullDepthCount = g.Count(p => p.OriginalDepth == null) };

这里的数据源是 SQLite 数据库中的一个表,使用 IQ 2.0.5.0 LINQPad 驱动程序链接到 LINQPad。错误信息是:

No generic method 'Where' on type 'System.Linq.Queryable' is compatible with the supplied type arguments and arguments. No type arguments should be provided if the method is non-generic.

我正在使用LINQPad v4.42.01。应用示例编译 vs .NET Framework 4 Client Profile

OriginalDepth 属性的类型为 double?

为什么我的查询在 LINQPad 中不起作用/为什么它在我的应用程序中起作用?

如何修复 LINQPad 查询?

更新

如果我将我的应用程序代码(包括虚拟Borehole 类的定义和虚拟data 列表的创建)复制并粘贴到LINQPad 中,它可以正常工作。因此,问题不在于 LINQPad 拒绝在应用程序中工作的查询格式。

问题变成了: 为什么我可以在 List<Borehole> 对象上使用 g.Count(p => p.OriginalDepth == null),但是当我对 LINQPad 访问的 SQLite 表执行相同的查询时,我得到了InvalidOperationException,如所述上面?

更新 2

查询的g.count 部分的谓词是什么并不重要。在对 SQLite 数据库表执行时,以下会导致相同的错误:

var lq2 = from p in Boreholes
          group p by p.CostCenter into g
          select new { NullDepthCount = g.Count(p => true )}; 

【问题讨论】:

  • 您确定数据(查询 1)== 钻孔(查询 2)吗?
  • 不,它们不一样,一个只是一个虚拟的,里面有手动创建的对象,另一个是实际的 SQLite 数据库内容,因此类是由 LINQPad 自动创建的。问题是为什么在 List<Borehole> 上允许该操作,但在 LINQPad 访问的表上却不允许。

标签: linq linqpad


【解决方案1】:

并非每个 Linq 提供程序都会支持所有功能,所以可能您在这里遇到了一个 IQ 提供程序不支持的功能。

如果表的大小很小(通常是 sqlite 数据库),那么你可以这样做

var lq = from p in Boreholes.ToList()
      group p by p.CostCenter into g
      select new {  CostCenter = g.Key, 
                    AverageDepth = g.Average(p => p.OriginalDepth),
                    NullDepthCount = g.Count(p => p.OriginalDepth == null) };

显然,这会将整个钻孔表加载到内存中,因此查询现在是一个 Linq To 对象查询,然后可以工作。

更新。

看起来也只是简单地替换

   NullDepthCount = g.Count(p => p.OriginalDepth == null)

在您的原始查询中

   NullDepthCount = g.Where(p => p.OriginalDepth == null).Count() 

会起作用,这意味着您不需要将数据带入内存。

【讨论】:

  • 感谢您的出色回答,g.Where().Count() 解决方法非常完美,如果我遇到类似情况,我会记住 .ToList() 技巧。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-18
相关资源
最近更新 更多