У меня очень сложный запрос 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, чтобы увидеть сгенерированный оператор 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. Это правильно?
EDIT:
В соответствии с приведенным ниже запросом, здесь приведена очень сжатая версия SQL, сгенерированная Linq, для краткости большинство столбцов результатов удалено. Он дает правильный результат в 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 Наконец, с помощью Microsoft пришли к правильному ответу. Пожалуйста, смотрите мой принятый ответ ниже для объяснения.