従来の Access アプリケーションを .NET Framework に移植していて、同じデータの並べ替え順序を維持する必要があります。同じデータベースに接続すると、ACCESS アプリケーションは次のように構成された ODBC 接続を使用します。
Microsoft SQL Server ネイティブ クライアント バージョン 11.00.2100
データ ソース名: Central Host-Set Database
データ ソースの説明:
サーバー: localhost\sqlexpress
統合セキュリティの使用: はい
データベース: CentralSQL15
言語: (デフォルト)
データ暗号化: いいえ
信頼サーバー証明書: いいえ
複数のアクティブな結果セット (MARS): いいえ
ミラーサーバー:
文字データの変換: はい
実行時間の長いクエリのログ: いいえ
ログ ドライバー統計: いいえ
地域設定の使用: いいえ
ANSI 引用符付き識別子
の使用: はい ANSI Null、パディング、および警告の使用: はい
.NET アプリケーションでは、もともと SQL Server への接続文字列で SqlClient を使用していましたが、Access とまったく同じ ODBC 接続を利用して、OdbcConnection/OdbcCommand/OdbcDataReader も使用してみました。ただし、ACCESS と .NET では常にソート順が異なります。
たとえば、次のクエリを使用します。
SELECT sessionstn3270.sessionid,
sessionnames.sessionname,
sessionstn3270.sessiontypeid,
sessionstn3270.usernameid,
sessionnames.host,
sessionnames.port,
lus.lu,
sessionnames.lastmodifiedsn,
templates.template,
templates.templatetype,
sessionnames.sessiontype
FROM (sessionnames
LEFT JOIN templates
ON sessionnames.template = templates.templateid)
INNER JOIN (sessionstn3270
LEFT JOIN lus
ON sessionstn3270.sessionid = lus.sessionid)
ON sessionnames.sessionnameid = sessionstn3270.sessionnameid
WHERE usernameid = 3978
ORDER BY templates.templatetype,
sessionnames.sessiontype;
SQL Management Studio と .NET アプリを使用すると、SessionID は次の順序で返されます。
17797
17798
17799
17800
17801
105372
MS Access では、次の順序で返されます。
17801
17800
17999
17998
17797
105372
95% の確率で、SessionID DESC を追加することで同じ検索結果を複製できますが、ORDER BY
100% ではありません。さまざまなフィールドでさまざまな並べ替え順序を試しましたが、100% の確率で機能するものはありません。
Access と .NET の間で返される結果の順序に他に何が影響するか知っている人はいますか?
http://expressprofiler.codeplex.com/から ExpressProfiler をダウンロードしたところ、次のものが見つかりました。
Access が SQL クエリを ACCESS データベースに送信すると、次のトランザクションが発生します。
SELECT "dbo"."SessionsTN3270"."SessionID" ,"dbo"."SessionsTN3270"."SessionID","dbo"."SessionNames"."SessionType" ,"dbo"."SessionNames"."SessionNameID","dbo"."Templates"."TemplateType" ,"dbo"."Templates"."TemplateID" FROM "dbo"."SessionsTN3270",\oj "dbo"."SessionNames" LEFT OUTER JOIN "dbo"."Templates" ON ("dbo"."SessionNames"."Template" = "dbo"."Templates"."TemplateID" ) \ WHERE (("dbo"."SessionsTN3270"."UserNameID" = 3978 ) AND ("dbo"."SessionNames"."SessionNameID" = "dbo"."SessionsTN3270"."SessionNameID" ) )
go
declare @p1 int
set @p1=1
exec sp_prepexec @p1 output,N'@P1 int',N'SELECT "SessionID" ,"dbo"."LUs"."LUID" FROM "dbo"."LUs" WHERE ("SessionID" = @P1)',17797
select @p1
go
exec sp_execute 1,17798
go
exec sp_execute 1,17799
go
exec sp_execute 1,17800
go
exec sp_execute 1,17801
go
exec sp_execute 1,105372
go
SELECT CASE DATABASEPROPERTYEX( DB_NAME(), 'Updateability') WHEN 'READ_ONLY' THEN 'Y' ELSE 'N' END
go
declare @p1 int
set @p1=1
exec sp_prepexec @p1 output,N'@P1 int,@P2 int,@P3 int,@P4 int,@P5 int,@P6 int,@P7 int,@P8 int,@P9 int,@P10 int',N'SELECT "TemplateID","Template","TemplateType" FROM "dbo"."Templates" WHERE "TemplateID" = @P1 OR "TemplateID" = @P2 OR "TemplateID" = @P3 OR "TemplateID" = @P4 OR "TemplateID" = @P5 OR "TemplateID" = @P6 OR "TemplateID" = @P7 OR "TemplateID" = @P8 OR "TemplateID" = @P9 OR "TemplateID" = @P10',15,15,15,15,15,33,33,33,33,33
select @p1
go
declare @p1 int
set @p1=2
exec sp_prepexec @p1 output,N'@P1 int,@P2 int,@P3 int,@P4 int,@P5 int,@P6 int,@P7 int,@P8 int,@P9 int,@P10 int',N'SELECT "SessionNameID","SessionName","Host","Template","SessionType","Port","LastModifiedSN","SSMA_TimeStamp" FROM "dbo"."SessionNames" WHERE "SessionNameID" = @P1 OR "SessionNameID" = @P2 OR "SessionNameID" = @P3 OR "SessionNameID" = @P4 OR "SessionNameID" = @P5 OR "SessionNameID" = @P6 OR "SessionNameID" = @P7 OR "SessionNameID" = @P8 OR "SessionNameID" = @P9 OR "SessionNameID" = @P10',204,203,202,201,200,272,272,272,272,272
select @p1
go
declare @p1 int
set @p1=3
exec sp_prepexec @p1 output,N'@P1 int,@P2 int,@P3 int,@P4 int,@P5 int,@P6 int,@P7 int,@P8 int,@P9 int,@P10 int',N'SELECT "SessionID","SessionTypeID","UserNameID","SessionNameID" FROM "dbo"."SessionsTN3270" WHERE "SessionID" = @P1 OR "SessionID" = @P2 OR "SessionID" = @P3 OR "SessionID" = @P4 OR "SessionID" = @P5 OR "SessionID" = @P6 OR "SessionID" = @P7 OR "SessionID" = @P8 OR "SessionID" = @P9 OR "SessionID" = @P10',17801,17800,17799,17798,17797,105372,105372,105372,105372,105372
select @p1
go
declare @p1 int
set @p1=4
exec sp_prepexec @p1 output,N'@P1 int,@P2 int,@P3 int,@P4 int,@P5 int,@P6 int,@P7 int,@P8 int,@P9 int,@P10 int',N'SELECT "LUID","SessionID","LU" FROM "dbo"."LUs" WHERE "LUID" = @P1 OR "LUID" = @P2 OR "LUID" = @P3 OR "LUID" = @P4 OR "LUID" = @P5 OR "LUID" = @P6 OR "LUID" = @P7 OR "LUID" = @P8 OR "LUID" = @P9 OR "LUID" = @P10',18539,18539,18539,18539,18539,18539,18539,18539,18539,18539
select @p1
go
SELECT "SessionTypeID" ,"SessionType" FROM "dbo"."SessionTypes" WHERE ("HostTypeID" = 200 )
go
SELECT "UserNameID" ,"WSUserName" ,"RecordType" ,"Role" ,"SecurityLevel" ,"BuildingCode" ,"FloorLevel" ,"ServerID" ,"Airline" ,"Description" ,"LastModified" FROM "dbo"."WSUsers"
go
ただし、SQL Server がクエリを実行する場合は、はるかに簡単です。
SELECT SessionsTN3270.SessionID, SessionNames.SessionName, SessionsTN3270.SessionTypeID, SessionsTN3270.UserNameID, SessionNames.Host, SessionNames.Port, LUs.LU, SessionNames.LastModifiedSN, Templates.Template, Templates.TemplateType, SessionNames.SessionType
FROM (SessionNames LEFT JOIN Templates ON SessionNames.Template = Templates.TemplateID) INNER JOIN (SessionsTN3270 LEFT JOIN LUs ON SessionsTN3270.SessionID = LUs.SessionID) ON SessionNames.SessionNameID = SessionsTN3270.SessionNameID WHERE UserNameID = 3978 ORDER BY Templates.TemplateType, SessionNames.SessionType;
go
この SQL トレースから、次のようにクエリを使用して SQL サーバーから同じ注文を複製できることがわかりました。
SELECT "dbo"."SessionsTN3270"."SessionID" ,"dbo"."SessionsTN3270"."SessionID","dbo"."SessionNames"."SessionType" ,"dbo"."SessionNames"."SessionNameID","dbo"."Templates"."TemplateType" ,"dbo"."Templates"."TemplateID" FROM "dbo"."SessionsTN3270", "dbo"."SessionNames" LEFT OUTER JOIN "dbo"."Templates" ON ("dbo"."SessionNames"."Template" = "dbo"."Templates"."TemplateID" )
WHERE (("dbo"."SessionsTN3270"."UserNameID" = 3978 ) AND ("dbo"."SessionNames"."SessionNameID" = "dbo"."SessionsTN3270"."SessionNameID" ) )