実稼働サーバーを 12.5 から 15 にアップグレードしたときに、.NET Framework 3.5 で実行され、 Sybase.Data.AseClient.dll (バージョン 1.1.510.0) を使用する一部のコードで、この問題が発生していました。すべてが開発環境とテスト環境でうまく機能しました。 ASP の従来のコードと PowerBuilder コードが実稼働の Sybase サーバー (大規模なレガシー システム) を呼び出すことができたにもかかわらず、アップグレード後に実稼働に失敗しました。
1 つのレコードに対してAseDataReaderのReadメソッドを呼び出してみたところ、すべて問題ありませんでした。しかし、すべてのレコードの読み取りを許可した場合、Sybase SQL Advandage クライアント経由でストアド プロシージャを呼び出した場合に取得される 67 レコードのうち、22 レコードしか読み取れません。問題を再現するために、おもちゃのコマンドラインアプリに煮詰めました。Readから出てくるエラーの詳細は次のとおりです。
Type: Sybase.Data.AseClient.AseException
Message: Internal Error: 30016
StackTrace: at Sybase.Data.AseClient.AseDataReader.?(Int32 A_0)
at Sybase.Data.AseClient.AseDataReader.?(Boolean A_0)
at Sybase.Data.AseClient.AseDataReader.?()
at Sybase.Data.AseClient.AseDataReader.Read()
at SybaseError.Program.TestCall(String friendlyName, String connectionString)
in C:\Projects\SybaseUpgradeError\SybaseError\Program.cs:line 42
usingブロックでIDataReader / AseDataReaderを宣言したと仮定すると、 Readからの元のエラーがスローされたときにリーダーが範囲外になったときに、実際には次のエラーが発生します。
Type: Sybase.Data.AseClient.AseException
Message: Internal Error: 30016
StackTrace: at Sybase.Data.AseClient.AseDataReader.?(Int32 A_0)
at Sybase.Data.AseClient.AseDataReader.?(Boolean A_0)
at Sybase.Data.AseClient.AseDataReader.?()
at Sybase.Data.AseClient.AseDataReader.?()
at Sybase.Data.AseClient.AseDataReader.?(Boolean A_0)
at Sybase.Data.AseClient.AseDataReader.NextResult()
at Sybase.Data.AseClient.AseDataReader.?()
at Sybase.Data.AseClient.AseDataReader.Close()
at Sybase.Data.AseClient.AseDataReader.?(Boolean A_0)
at Sybase.Data.AseClient.AseDataReader.Dispose()
at SybaseError.Program.TestCall(String friendlyName, String connectionString)
in C:\Projects\SybaseUpgradeError\SybaseError\Program.cs:line 54
AseDataReaderのDisposeメソッドが例外をスローしていることに気付くでしょう。これは大したことではありません。さらに悪いことに、例外をAseExceptionとしてキャッチし、 Errorsコレクション プロパティを反復処理すると、それらを読み取ると例外がスローされます。どうやら、AseErrorオブジェクトのプロパティをチェックすると、実際にはプロパティ内の動的コードが呼び出され、アクティブな接続から何かを調べようとします。このバージョンの Sybase .NET クライアント コードには特に感銘を受けません。
この問題は、実稼働サーバーと開発サーバーおよびテスト サーバーで異なるパケット サイズ設定に要約されました。管理者アクセス権はありませんが、開発サーバーとテスト サーバーでは最小 2048 と最大 4096 に設定されていましたが、運用サーバーでは最小と最大の両方が 4096 に設定されていたと思います。これは電話会議の私の記憶に基づいているため、マイレージは異なる場合があります. 後で他の人に役立つ場合に備えて、ここに掲載したかっただけです。問題を追跡するのにしばらく時間がかかりました。最小パケット サイズを変更し、運用データベース サーバーを再起動すると、問題は解決しました。
参考までに、接続文字列をスクラブしたテスト コンソール アプリを次に示します。繰り返しますが、一番下のコメント行は、コメントを外すとエラーをスローします。これがお役に立てば幸いです!
using System;
using System.Data;
using Sybase.Data.AseClient;
namespace SybaseError
{
public class Program
{
public static void Main(string[] args)
{
const string DevelopmentConnection = "Data Source='**********';Port='****';UID='**********';PWD='**********';Database='**********';";
const string ReportConnection = "more secret stuff";
const string ProductionConnection = "yet more secret stuff";
TestCall("Development", DevelopmentConnection);
TestCall("Report", ReportConnection);
TestCall("Production", ProductionConnection);
Console.ReadKey();
}
private static void TestCall(string friendlyName, string connectionString)
{
Console.WriteLine("Calling procedure on " + friendlyName + ".");
int recordsRead = 0;
try
{
using (var connection = new AseConnection(connectionString))
{
connection.Open();
using (var command = connection.CreateCommand())
{
ConfigureCommand(command);
using (var reader = command.ExecuteReader(CommandBehavior.CloseConnection))
{
try
{
while (reader.Read())
{
// Would usually read things here...
recordsRead++;
}
}
catch (Exception exRead)
{
Console.WriteLine("Error on read:");
ShowError(exRead);
throw;
}
}
}
}
Console.WriteLine("Success calling procedure on " + friendlyName + ".");
}
catch (Exception ex)
{
Console.WriteLine("Outer error:");
ShowError(ex);
Console.WriteLine("Failure calling procedure on " + friendlyName + ".");
}
Console.WriteLine("Finished calling procedure on " + friendlyName + ". Read " + recordsRead + " records.");
Console.WriteLine(string.Empty);
}
private static void ConfigureCommand(AseCommand command)
{
command.CommandText = "sp_s_educator_route_tests";
command.CommandType = CommandType.StoredProcedure;
var spidParameter = new AseParameter("@spid", AseDbType.Integer);
spidParameter.Value = 1355945;
command.Parameters.Add(spidParameter);
var vendorIdParameter = new AseParameter("@vendor_id", AseDbType.Integer);
vendorIdParameter.Value = 1;
command.Parameters.Add(vendorIdParameter);
}
private static void ShowError(Exception ex)
{
Console.WriteLine("Type: " + ex.GetType());
Console.WriteLine("Message: " + ex.Message);
Console.WriteLine("StackTrace: " + ex.StackTrace);
var exAse = ex as AseException;
if (exAse != null)
{
//foreach (AseError error in exAse.Errors)
//{
// Console.WriteLine("SqlState: " + error.SqlState);
// Console.WriteLine("State: " + error.State);
//}
}
}
}
}