2009-11-10 1 views
2

Есть ли у кого-нибудь идеи, почему SubSonic 2.2 SubSonic.SqlQuery-объект будет генерировать очень разные sql для того же кода на C#, когда работает с SQL Server 2005 или SQL Server 2008?SubSonic 2.2 Объект SqlQuery генерирует очень разные sql для оператора WHERE ... IN для SQL Server 2008 и SQL Server 2005

У меня есть сайт, который был запущен на некоторое время на дозвуковых 2,2/SQL Server 2005. Я обновил БД на MSSQL 2008 и я встречая следующее сообщение об ошибке:

SqlException (0x80131904): Incorrect syntax near the keyword 'AND'

Я вывалил SQLQuery .ToString() в точке отказа и заметил следующие различия между запуском точно так же кодовую на SQL Server 2005 и SQL Server 2008. Вот исходный код:

SubSonic.SqlQuery q = new Select() 
    .From(Views.VwSearchIndexQuery2Mtx) 
    .Paged(pageNumber, maximumRows) 
    .Where(VwSearchIndexQuery2Mtx.Columns.SearchIndexQueryId) 
    .In(
     new Select(SearchIndexQueryGroupMap.Columns.SearchIndexQueryId) 
      .From(Tables.SearchIndexQueryGroupMap) 
      .Where(SearchIndexQueryGroupMap.Columns.SearchIndexQueryGroupId) 
      .IsEqualTo(searchIndexQueryGroupId)); 

и автоматически сгенерированный SQL для SQL Сервер 2005:

SELECT * FROM  
(SELECT ROW_NUMBER() OVER (ORDER BY CreatedOn DESC) AS Row 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryId] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryName] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchTerms] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexId] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexName] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[IndustryId] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[IndustryName] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[DaysMonitored] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[Incidents] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[Relevance] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[CreatedOn] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[CreatedBy] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[ModifiedOn] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[ModifiedBy] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[Deleted] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryTypeId] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryTypeName] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[LastUpdatedTime]  
FROM [dbo].[Vw_SearchIndexQuery2_Mtx]  
WHERE [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryId] 
IN (SELECT [dbo].[SearchIndexQueryGroup_Map].[SearchIndexQueryId] 
FROM [dbo].[SearchIndexQueryGroup_Map] 
WHERE [dbo].[SearchIndexQueryGroup_Map].[SearchIndexQueryGroupId] = @SearchIndexQueryGroupId0) )    
AS PagedResults WHERE Row >= 1 AND Row <= 20 

автоматически сгенерированное SQL для SQL Server 2008:

DECLARE @Page int  
DECLARE @PageSize int  
SET @Page = 1  
SET @PageSize = 20  
SET NOCOUNT ON  
-- create a temp table to hold order ids  
DECLARE @TempTable TABLE (IndexId int identity, _keyID Int)  
-- insert the table ids and row numbers into the memory table  
INSERT INTO @TempTable  (  _keyID  )  
SELECT  [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryId]   
FROM [dbo].[Vw_SearchIndexQuery2_Mtx] 
WHERE [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryId] 
IN (SELECT [dbo].[SearchIndexQueryGroup_Map].[SearchIndexQueryId] 
    FROM [dbo].[SearchIndexQueryGroup_Map] 
    WHERE [dbo].[SearchIndexQueryGroup_Map].[SearchIndexQueryGroupId] 
         = @SearchIndexQueryGroupId0 
    ) 
    /* it's at this next AND where the error is thrown */ 
AND [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryId] 
IN (SELECT [dbo].[SearchIndexQueryGroup_Map].[SearchIndexQueryId] 
    FROM [dbo].[SearchIndexQueryGroup_Map] 
    AND [dbo].[SearchIndexQueryGroup_Map].[SearchIndexQueryGroupId] 
         = @SearchIndexQueryGroupId0 
       ) 
ORDER BY CreatedOn DESC  
-- select only those rows belonging to the proper page   
SELECT [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryId] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryName] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchTerms] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexId] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexName] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[IndustryId] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[IndustryName] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[DaysMonitored] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[Incidents] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[Relevance] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[CreatedOn] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[CreatedBy] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[ModifiedOn] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[ModifiedBy] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[Deleted] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryTypeId] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryTypeName] 
, [dbo].[Vw_SearchIndexQuery2_Mtx].[LastUpdatedTime] 
FROM [dbo].[Vw_SearchIndexQuery2_Mtx]  
INNER JOIN @TempTable t ON [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryId] = t._keyID  
WHERE t.IndexId BETWEEN ((@Page - 1) * @PageSize + 1) AND (@Page * @PageSize) 

Я знаю, почему происходит ошибка - SQL, является недействительным и что я заметил выше. Я просто не могу понять, почему SubSonic генерирует недопустимый SQL после того, как он работал на SQL Server 2008. Вы увидите, что для SQL Server 2008 он использует временную таблицу, и это также похоже на повторение раздела WHERE ... IN, запрос. Я подумал, что, возможно, это был уровень совместимости ISO, так как обновленная БД была установлена ​​на 100. Таким образом, я протестировал с установкой его как на 90 & 80, так и SubSonic генерирует тот же sql, что и в каждом случае. (И BTW, код, созданный для SQL Server 2005, который использует «select rownumber() over ..., поскольку строка« отлично работает с SQL Server 2008.)

Есть ли у кого-нибудь идеи, почему это происходит и как отслеживать это вниз?

Большое спасибо,

Терри

+0

Этот вопрос заставил меня пройти через цикл на некоторое время, так как дублирующие условия также произошли в другой проблеме, которую я обновил до 2.2 от 2.1 до исправления. Я связался здесь с моим вопросом SF http://serverfault.com/questions/174166/asp-net-site-on-iis-7-5-not-taking-new-version-of-3rd -party-dll – ManiacZX

ответ

2

Это, возможно, было зафиксировано уже в источнике? Я предлагаю вам попробовать самый последний источник от github, чтобы узнать, была ли проблема устранена.

В принципе, это, как вы сказали, генератор 2005 переопределяет метод BuildPagedSelectStatement(), предоставляемый ANSISqlGenerator. Генератор 2008 наследует от 2005 года, так что следует использовать тот же метод подкачки в 2005

Это можно увидеть, сравнивая эти twofiles:

Я считаю, вы бы также видеть поведение вы описываете в базе данных SQL 2000, поскольку он не переопределяет метод ANSISqlGenerator.BuildPagedSelectStatement().

Кроме того, I don't think compatability level is used для определения SQL генератора:

public static bool IsSql2008(DataProvider provider) 
    { 
     return provider.DatabaseVersion.IndexOf("2008 - 10.") > -1 || 
     provider.DatabaseVersion.IndexOf("2008 (RTM) - 10.") > -1; 
    } 

И, если предположить, что ANSI generator является то, что на самом деле используется, проблема с и может быть вызвано этой линии в BuildPagedSqlStatement():

//have to doctor the wheres, since we're using a WHERE in the paging 
    //bits. So change all "WHERE" to "AND" 
    string tweakedWheres = wheres.Replace("WHERE", "AND"); 

Это должно быть немного умнее этого, хотя нужно также обратить внимание на то, что вы поднимаете о дублированном пункте.

+0

Вот и все, в AnsiGenerator есть кое-что немного, вызывающее дублирующее предложение. Поскольку я ни от кого не слышал, я схватил последний код из github и отследил его до метода IsSql2008(), пока вы отправили свой ответ. – tblank

+0

Что происходит в моем случае, так это то, что логика падает через оператор switch и заканчивается использованием генератора ANSI, потому что мой провайдер.DatabaseVersion = «Microsoft SQL Server 2008 (SP1) - 10.0.2531.0. ...» Кажется, мне может быть лучший способ структурировать логику в этом методе. Было бы целесообразнее добавить еще один тест, например: || provider.DatabaseVersion.IndexOf ("2008 (SP1) - 10.")> -1 или упростить его до 1 теста для: provider.DatabaseVersion.IndexOf ("2008")> -1 – tblank

+0

Есть ли предпочтительный способ для меня передать эту информацию кому-то, кто может быть более искусным, чем я, чтобы вернуть его в исходный код? Спасибо за ваш ответ. – tblank

1

Только что столкнулся с этой ошибкой и очень рад, что нашел эту страницу, потому что я понятия не имел, почему это происходит.

Похоже, что запуск SQL Server 2008 с пакетом обновления 1 (SP1) приводит к тому, что IsSql2008 является FALSE. Поскольку возвращаемый DatabaseVersion (на моей машине) возвращается как «Microsoft SQL Server 2008 (SP1) - 10.0.2531.0 (X64) ...», который не соответствует критериям функции IsSql2008.

Похоже, что это еще не было адресовано на кодовой базе github?

Почему бы не иметь что-то проще, как

if (provider.DatabaseVersion.Contains("SQL Server 2008")) 
+0

Ahh только что заметил, что он уже находится в списке проблем, но все еще открыт (не был реализован и был отправлен 5 месяцев назад ...): http://github.com/subsonic/SubSonic -2,0/вопросы # вопрос/7 –

Смежные вопросы