【发布时间】:2009-11-17 21:27:30
【问题描述】:
我有一个非常复杂的 Linq to SQL 查询,它从 Microsoft SQL Server 数据库返回一个结果集。查询是使用类似于以下的语法创建的:
Dim db as MyDataContext = MyGetDataContextHelper()
Dim qry = From rslt in db.MyView Select ColumnList
If userParam1 IsNot Nothing Then
qry = qry.Where(lambda for the filter)
End If
etc....
Return qry.ToList()
有几个用户指定的查询过滤器,包括一个进行地理半径搜索的过滤器。
这就是问题所在。我在最后的“ToList”调用上设置了一个休息时间。当中断被击中时,我使用 Linq to SQL Debug Visualizer 查看生成的 SQL 语句。我将该复杂的 SQL 语句复制到 SQL Server Management Studio 查询窗口中,并针对我的数据库执行它以获得我想要的结果集。所以生成的 SQL 似乎产生了预期的结果。但是,当我执行查询对象的“ToList”方法时,返回的列表具有较少的行和一些不同的行。我也尝试过使用 DataContext 日志属性写入文件,结果相同。该查询在 SQL Management Studio 中生成正确的结果集,但从 ToList 方法生成的结果不正确。
怎么可能?如果生成的 SQL 只是通过与 SQL Server 的连接传递,它不应该完全生成我在 SQL Server Management Studio 中看到的结果集吗?我假设我对 Linq to SQL 机制有一些误解,即它不仅仅是对 SQL Server 的传递。对吗?
编辑: 根据下面的请求,这里是由 Linq 生成的 SQL 的一个非常精简的版本,为简洁起见,删除了大部分结果列。它在 SQL Management Studio 中产生正确的结果,但返回给我的应用程序的结果不同。
SELECT [t3].[Id]
FROM (
SELECT DISTINCT [t1].[Id]
FROM (
SELECT [t0].[Id], [t0].[ItemDate]
FROM [dbo].[MySearchView] AS [t0]
) AS [t1]
WHERE (EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[ZipCoverage] AS [t2]
WHERE ([t2].[Id] = [t1].[Id])
AND ([t2].[Latitude] >= (41.09046 - (0.5)))
AND ([t2].[Latitude] <= (41.09046 + (0.5)))
AND ([t2].[Longitude] >= (-73.43106 - (0.5)))
AND ([t2].[Longitude] <= (-73.43106 + (0.5)))
AND (ABS(3956.08833132861 * 2 * ATN2(SQRT(POWER(SIN((((CONVERT(Float,CONVERT(Float,0.0174532925199433))) * [t2].[Latitude]) - 0.717163818159029) / (CONVERT(Float,2))), 2) + (COS(0.717163818159029) * COS((CONVERT(Float,CONVERT(Float,0.0174532925199433))) * [t2].[Latitude]) * POWER(SIN((((CONVERT(Float,CONVERT(Float,0.0174532925199433))) * [t2].[Longitude]) - -1.28161377022951) / (CONVERT(Float,2))), 2))), SQRT((1 - POWER(SIN((((CONVERT(Float,CONVERT(Float,0.0174532925199433))) * [t2].[Latitude]) - 0.717163818159029) / (CONVERT(Float,2))), 2)) + (COS(0.717163818159029) * COS((CONVERT(Float,CONVERT(Float,0.0174532925199433))) * [t2].[Latitude]) * POWER(SIN(((CONVERT(Float,CONVERT(Float,0.0174532925199433))) * [t2].[Longitude]) / (CONVERT(Float,2))), 2))))) <= 5)))
AND ([t1].[ItemDate] <= '11/17/2009 8:12:42 PM')
) AS [t3]
更新 2009-11-17 能够就这个问题联系 MS。创建了一个示例应用程序,我将其提交给了他们的支持代表。他们已经复制了这个问题并正在研究。收到回复后会发布答案。
更新 2009-12-21 在微软的帮助下终于得到了正确的答案。请参阅下面我接受的答案以获得解释。
【问题讨论】:
-
能否请您发布您的实际 LINQ 查询?你说这很复杂。鉴于其他一切似乎都井然有序,剩下的选择是您的 LINQ 查询包含仅运行时处理,翻译器无法将其转换为 SQL。
-
我在下面回复了您对我的回答的评论。
-
没有ORDER BY吗?我们讨论了多少行,您如何验证结果是否不同?有没有可能是顺序不同,结果看起来不一样?
-
有一个 ORDER BY 子句,为简洁起见,我将其删除。我通过行数验证结果 - SQL Management Studio 中的查询为 13 个,Linq 的 ToList 返回为 8 个 - 以及 ID 列,其中一些相同,一些不同。
-
您是否验证了调试输出显示的查询实际上是 Linq 发送到服务器的内容?我会运行快速跟踪以查看实际传递的内容,然后将其与您在 Management Studio 中运行的内容进行比较。除此之外,我没有任何其他建议,抱歉。
标签: .net sql-server linq linq-to-sql