Мы столкнулись с этой проблемой, когда какой-то код работал в .NET Framework 3.5 и использовал Sybase.Data.AseClient.dll (версия 1.1.510.0), когда мы обновили наш рабочий сервер с 12.5 до 15. После обновления все работало хорошо в средах разработки и тестирования, но не работало в рабочей среде, хотя классический код ASP и код PowerBuilder могли вызывать производственный сервер Sybase (большая устаревшая система).
Если я попытался вызвать Read метод AseDataReader для отдельной записи, все было в порядке. Но если бы мы разрешили читать все записи, он прочитал бы только 22 из 67 записей, которые были бы получены, если бы вы вызвали хранимую процедуру через клиент Sybase SQL Advandage. Я свел его к игрушечному приложению командной строки, чтобы воспроизвести проблему. Вот подробности ошибки, которые могут появиться из 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
Предполагая, что вы объявили свой 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
Вы заметите, что метод Dispose AseDataReader вызывает исключение, которое является большим нет-нет. Еще хуже то, что если вы перехватываете исключение как AseException и перебираете свойство коллекции Errors , при чтении эти исключения будут выбрасываться. По-видимому, проверка свойств объекта AseError на самом деле вызывает некоторый динамический код в свойстве, который пытается искать вещи из активного соединения. Я не особенно впечатлен этой версией клиентского кода Sybase .NET.
Проблема сводилась к настройке размера пакета, которая отличалась на производственном сервере от серверов разработки и тестирования. У меня нет доступа администратора, но я полагаю, что они были установлены на min 2048 и max 4096 на серверах разработчика и тестирования, но и min, и на max установлены 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);
//}
}
}
}
}