【问题标题】:'Invalid column name [ColumnName]' on a nested linq query嵌套 linq 查询中的“无效列名 [ColumnName]”
【发布时间】:2011-03-08 23:37:41
【问题描述】:

上次更新

经过大量测试后,我意识到如果我在 SQL 2000 和 SQL 2005 上对同一个数据集(在本例中为 Northwind)表运行相同的查询,我会得到两个不同的结果。 在 SQL 2000 上,我得到了问题中的错误。 在 SQL 2005 上,它成功了。

所以我得出结论,linqpad 生成的查询不适用于 sql 2000。要重现此问题,请运行:

OrderDetails
    .GroupBy(x=>x.ProductID)
    .Select(x=>new {product_id = x.Key, max_quantity = x.OrderByDescending(y=>y.UnitPrice).FirstOrDefault().Quantity}).Dump();

在 sql 2000 中的 Northwind DB 上。sql 翻译是:

SELECT [t1].[ProductID] AS [product_id], (
    SELECT [t3].[Quantity]
    FROM (
        SELECT TOP 1 [t2].[Quantity]
        FROM [OrderDetails] AS [t2]
        WHERE [t1].[ProductID] = [t2].[ProductID]
        ORDER BY [t2].[UnitPrice] DESC
        ) AS [t3]
    ) AS [max_quantity]
FROM (
    SELECT [t0].[ProductID]
    FROM [OrderDetails] AS [t0]
    GROUP BY [t0].[ProductID]
    ) AS [t1]

原始问题

我有以下查询:

ATable
.GroupBy(x=> new {FieldA = x.FieldAID, FieldB = x.FieldBID, FieldC = x.FieldCID})
.Select(x=>new {FieldA = x.Key.FieldA, ..., last_seen = x.OrderByDescending(y=>y.Timestamp).FirstOrDefault().Timestamp})

结果:

SqlException: Invalid column name 'FieldAID' x 5
SqlException: Invalid column name 'FieldBID' x 5
SqlException: Invalid column name 'FieldCID' x 1

我发现它与对 Timestamp 的最后一次查询有关,因为它有效:

ATable
.GroupBy(x=> new {FieldA = x.FieldAID, FieldB = x.FieldBID, FieldC = x.FieldCID})
.Select(x=>new {FieldA = x.Key.FieldA, ...,  last_seen = x.OrderByDescending(y=>y.Timestamp).FirstOrDefault()})

查询已被简化。目的是按一组变量进行分组,然后显示该分组最后一次在数据库中发生的时间。

我正在使用 Linqpad 4 生成这些结果,因此 Timestamp 为我提供了一个字符串,而 FirstOrDefault 为我提供了不理想的整个对象。

更新
在进一步的测试中,我注意到 SQLException 的数量和类型与 groupby 子句中创建的类有关。 所以,

ATable
.GroupBy(x=> new {FieldA = x.FieldAID})
.Select(x=>new {FieldA = x.Key.FieldA, last_seen = x.OrderByDescending(y=>y.Timestamp).FirstOrDefault()})

结果

SqlException: Invalid column name 'FieldAID' x 5

【问题讨论】:

  • 为什么要使用匿名类型来存储一个字段? (last_seen)
  • 啊,是的,正如我在我的问题中所说,查询已被简化(相当显着)以消除不相关的废话。运行简单查询仍然给我错误。该 select 语句实际上包含多个字段,然后依次由 orderby、thenby、select 和最后一个转储处理。
  • 也许你应该发布一个简单的模式来重新创建。我已尝试创建一个带有所描述的时间戳列的表,但无法重现。
  • 我已经在北风桌 OrderDetails .GroupBy(x=>x.ProductID) .Select(x=>x.OrderByDescending(y=>y.UnitPrice).FirstOrDefault().UnitPrice).Dump(); 和 OrderDetails .GroupBy(x=>x.ProductID) .Select(x=>x.Max(y=>y.UnitPrice)).Dump(); 上尝试过这个,两者都有效。尝试在该表上重现它并呈现结果。
  • 我在 Sql2000 数据库错误中遇到同样的错误,但 Max 可以正常工作,您可以尝试将原始查询更改为 ATable .GroupBy(x=> new {FieldA = x.FieldAID, FieldB = x.FieldBID, FieldC = x.FieldCID}) .Select(x=>new {FieldA = x.Key.FieldA, ..., last_seen = x.Max(y=>y.Timestamp)})

标签: c# sql-server linq linqpad sqlexception


【解决方案1】:

您应该使用 SQL 分析器检查针对 2 个数据库生成的 SQL 是否不同。

我们只有两个问题,即在 SQL Server 2005 上运行但在 SQL Server 2000 上没有运行。在这两种情况下,都是由于 SQL Server 2000 中缺乏对多个活动结果集 (MARS) 的支持。在一种情况下它会导致数据库锁定,在另一种情况下会导致性能下降。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-12
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 2017-11-29
    • 1970-01-01
    相关资源
    最近更新 更多