2

SQLServer2005またはSQLServer2008に対して実行したときに、SubSonic 2.2 SubSonic.SqlQueryオブジェクトが同じC#コードに対して非常に異なるSQLを生成する理由を誰かが知っていますか?

SubSonic 2.2 / SQL Server 2005でしばらく実行されているサイトがあります。DBをmssql2008にアップグレードしたところ、次のエラーが発生しました。

SqlException(0x80131904):キーワード「AND」の近くの構文が正しくありません

失敗した時点でSqlQuery.ToString()をダンプしましたが、SQLServer2005とSQLServer2008でまったく同じコードベースを実行する場合の次の違いに気づきました。ソースコードは次のとおりです。

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));

また、SQLServer2005用に自動生成されたSQLは次のとおりです。

 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 Server 2008用に自動生成されたSQL:

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は、上記でコメントしたANDによって無効になっています。SubSonicがSQLServer2008で動作した後、無効なSQLを生成している理由がわかりません。SQLServer2008の場合、一時テーブルを使用しており、WHERE...INサブを繰り返しているように見えます。クエリ。アップグレードされたDBが100に設定されていたので、おそらくISO互換性レベルだと思いました。90と80の両方に設定してテストしたところ、SubSonicはそれぞれの場合と同じSQLを生成します。(ところで、「select rownumber()over ...asrow」を使用するSQLServer2005用に生成されたコードは、SQL Server 2008に対して正常に実行されます。)

なぜこれが起こっているのか、そしてそれを追跡する方法について誰かが何か考えを持っていますか?

どうもありがとう、

テリー

4

3 に答える 3

2

これはソースですでに修正されている可能性がありますか?githubの最新のソースを試して、問題が解決されているかどうかを確認することをお勧めします。

基本的に、あなたが言ったように、2005ジェネレーターはANSISqlGeneratorによって提供されるBuildPagedSelectStatement()メソッドをオーバーライドします。2008ジェネレーターは2005を継承しているため、2005と同じページング方法を使用する必要があります。

これは、これら2つの ファイルを比較することで確認できます。

これは、ANSISqlGenerator.BuildPagedSelectStatement()メソッドをオーバーライドしないため、SQL2000データベースで説明している動作も表示されると思います。

また、互換性レベルがSQLジェネレーターの決定に使用されているとは思いません。

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

また、ANSIジェネレーターが実際に使用されているものであると仮定すると、ANDの問題は、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");

重複した条項について提起する点にも対処する必要がありますが、それよりも少し賢くする必要があります。

于 2009-11-12T01:30:56.030 に答える
1

このエラーが発生したばかりで、なぜこのページが発生したのかわからなかったので、このページを見つけてとてもうれしく思います。

SQL Server 2008 SP1を実行すると、IsSql2008がFALSEになるようです。返されたDatabaseVersion(私のマシン上)は「MicrosoftSQL Server 2008(SP1)-10.0.2531.0(X64)...」として返されるため、IsSql2008関数の基準を満たしていません。

これはまだgithubコードベースで対処されていないようですか?

こんなにシンプルなものを作ってみませんか

if (provider.DatabaseVersion.Contains("SQL Server 2008"))
于 2010-04-28T10:14:07.337 に答える
1

この問題はここに記載されています。修正をフォークしてコミットしたので、まもなく含まれるはずです。

于 2010-09-17T01:25:45.477 に答える