Windows フォーム アプリケーション (.NET 2.0) の一部のレポートで使用される Visual Studio のテーブル アダプター デザイナーで定義されたいくつかのクエリを維持しています。アプリケーションを実行して特定のクエリを実行すると、次のエラーが表示されます。式をデータ型 smallmoney に変換すると、算術オーバーフロー エラーが発生します。クエリはかなり少量を生成するはずなので、私は驚いたので、SQL プロファイラーでクエリをキャプチャし、SQL Server Management Studio で (明らかに同じデータベースで) まったく同じクエリを実行しました。ここで、クエリは問題なく実行され、smallmoney は "33.00" です。214,748.3647 境界のどこにもありません。
デバッグを複雑にするために、この問題はクライアントの QA 環境でのみ発生し、ローカルでは再現できません (また、法的な理由により、データベースを開発環境にコピーすることはできません)。これにより、クライアントの環境で新しいバージョンをビルドして展開するのに最大 30 分かかるため、デバッグ サイクルが非常に遅くなります。そのため、できるだけ少ない実験でこの問題を特定するためのヒントをいただければ幸いです。SQL Studio でクエリをいじっても、同じエラーを発生させることはできないため、あまり役に立ちません。
クエリは次のとおりです。
SELECT CONVERT(varchar, Events.Occurred, 102) AS Day, Users.Name, COUNT(*) AS Deleted_Invoices, SUM(i.TotalExVat + i.TotalVat) AS Total
FROM Events WITH (nolock) INNER JOIN
Users WITH (nolock) ON Events.UserID = Users.UserID INNER JOIN
Types AS t WITH (nolock) ON t.TypeID = Events.TypeID INNER JOIN
InvoicesEvents AS ie ON ie.EventID = Events.EventID INNER JOIN
Invoices AS i ON i.InvoiceID = ie.InvoiceID
WHERE (Events.Occurred BETWEEN @startDate AND @endDate) AND (t.Name = 'InvoiceDeleted')
GROUP BY CONVERT(varchar, Events.Occurred, 102), Users.Name
ORDER BY Day, Users.Name
TotalExVat および TotalVat は smallmoney ではありません。データ テーブルの「Total」フィールドは、「System.Decimal」にマップされます。式で smallmoney を money にキャストすることもできますが、SQL スタジオで正常に実行されるのに、なぜそれを行う必要があるのでしょうか?
私が取得する例外は次のとおりです。
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlDataReader.HasMoreRows()
at System.Data.SqlClient.SqlDataReader.ReadInternal(Boolean setTimeout)
at System.Data.SqlClient.SqlDataReader.Read()
at System.Data.Common.DataAdapter.FillLoadDataRow(SchemaMapping mapping)
at System.Data.Common.DataAdapter.FillFromReader(DataSet dataset, DataTable datatable, String srcTable, DataReaderContainer dataReader, Int32 startRecord, Int32 maxRecords, DataColumn parentChapterColumn, Object parentChapterValue)
at System.Data.Common.DataAdapter.Fill(DataTable[] dataTables, IDataReader dataReader, Int32 startRecord, Int32 maxRecords)
at System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.Fill(DataTable[] dataTables, Int32 startRecord, Int32 maxRecords, IDbCommand command, CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.Fill(DataTable dataTable)
at ... (calling code)
アップデート
SUM(i.TotalExVat + i.TotalVat) を SUM(i.TotalExVat) + SUM(i.TotalVat) に変更するとエラーが解消されましたが、生成された結果に小さなお金のオーバーフローがないため、その理由はまだわかりません。
更新 2
新しい問題。スモールマネーのキャスティングの問題はなくなりましたが、タイムアウトの問題が発生しました。同じレポートで使用される別のクエリは、SSMS で実行した場合、約 5 ~ 6 秒で実行されます。テーブル アダプタで実行すると、10 分後にタイムアウトします。他のクエリは期待どおりに実行され、SSMS と同じ結果が生成されます。これは、テーブル アダプターがデータベースにクエリを実行しようとすると、何かがおかしいという私の疑いを裏付けるものです。
アップデート 3
これは奇妙になり始めています。小額問題のクエリは、レポートを生成するために使用される一連のクエリの 5 番目のクエリを埋めます。最初の更新に記載されている修正を適用した後、最初のクエリでタイムアウトが発生します。後のクエリで smallmoney がオーバーフローしていたとき、そのクエリは問題なく実行されました。その理由は何でしょうか?
smallmoney クエリでエラーが発生したときに実行され、動作しているときに実行されていないクエリ:
SELECT u.Name AS Username, rea.Text AS DeleteReason, COUNT(*) AS DeletedRegistrations, SUM(r.Shipments) AS DeletedShipments
FROM RecordingsEvents AS re WITH (nolock) INNER JOIN
Events AS e WITH (nolock) ON e.EventID = re.EventID INNER JOIN
Reasons AS rea WITH (nolock) ON rea.ReasonID = e.ReasonID INNER JOIN
Users AS u WITH (nolock) ON u.UserID = e.UserID INNER JOIN
Recordings AS r ON r.RecordingID = re.RecordingID
WHERE (rea.Category = 'DeleteRecording') AND (e.Occurred BETWEEN @startDate AND @endDate)
GROUP BY u.Name, rea.Text
ORDER BY Username, MAX(rea.SortOrder)
smallmoney クエリの結果が 30.0.0.0 である日付間隔を制限すると、上記のクエリは機能します。smallmoney クエリも失敗していた期間に日付間隔を拡張すると、タイムアウトが発生します。smallmoney クエリが失敗したときに正常に実行されたときに、smallmoney クエリの前に実行されるクエリでタイムアウトを取得するにはどうすればよいですか? SSMS ですべてのクエリを実行すると、期待どおりに動作します。ところで、クエリは同期的に実行されます。