SQL Server: не удалось найти подготовленный оператор с дескриптором x - PullRequest
1 голос
/ 03 сентября 2011

Недавно наша команда QA сообщила об очень интересной ошибке в одном из наших приложений.Наше приложение представляет собой приложение на основе C # .Net 3.5 с пакетом обновления 1 (SP1), взаимодействующее с базой данных SQL Server 2005 Express Edition.

По своему замыслу приложение разработано для обнаружения сценариев автономной работы с базой данных и, если да, для ожидания подключения к базе данных (повторная попытка подключиться своевременно) и после подключения снова подключиться и возобновить работу.

То, что сделала наша команда QA, пока приложение извлекало большую часть данных из базы данных, остановите сервер базы данных, дождитесьнекоторое время и перезапустите базу данных.Как только база данных перезапускается, приложение повторно подключается к базе данных без каких-либо проблем, но оно начинает непрерывно сообщать об исключении «Не удалось найти подготовленный оператор с дескриптором x» (x - это некоторое число).

Наше приложение использует подготовленные операторыи он уже предназначен для повторного вызова метода Prepare () для всех объектов SqlCommand при повторном подключении приложения к базе данных.Например,

При запуске приложения

    SqlCommand _commandA = connection.CreateCommand();
    _commandA.CommandText = @"SELECT COMPANYNAME FROM TBCOMPANY WHERE ID = @ID";
    _commandA.CommandType = CommandType.Text;
    SqlParameter _paramA = _commandA.CreateParameter();
    _paramA.ParameterName = "@ID";
    _paramA.SqlDbType = SqlDbType.Int;
    _paramA.Direction = ParameterDirection.Input;
    _paramA.Size = 0;
    _commandA.Parameters.Add(_paramA);
    _commandA.Prepare();

После этого мы используем ExceuteReader () для этой _команды с различными значениями параметров @ID в каждом цикле приложения.

Как только приложение обнаружит, что база данных отключена и снова подключена, при повторном подключении к базе данных приложение только выполняет,

    _commandA.Prepare();

Еще две странные вещи, которые мы заметили.1. Описанная выше ситуация возникает с командами типа CommandType.Text в коде.Наше приложение также использует ту же самую логику для вызова хранимых процедур, но мы никогда не сталкиваемся с этой проблемой с помощью хранимых процедур.2. До сих пор нам не удавалось воспроизвести эту проблему независимо от того, сколько разных способов мы пробовали ее в режиме отладки в Visual Studio.

Заранее спасибо ..

Ответы [ 3 ]

1 голос
/ 05 сентября 2011

Я думаю, что после почти 3 дней задавания вопроса и около 20 просмотров вопроса и 1 ответа я должен сделать вывод, что это не тот сценарий, с которым мы можем справиться так, как пытались использовать SQL-сервер.

Лучший способ устранить эту проблему в вашем приложении - заново создать экземпляр объекта SqlCommand, как только приложение обнаружит, что база данных подключена.

Мы внесли изменения в наше приложение, и наша команда QA рада этой модификации, поскольку она предоставила лучшее (или, возможно, единственное) исправление для проблемы, о которой они сообщили.

Последнее спасибо всем, кто просмотрел и ответил на вопрос.

0 голосов
/ 23 июля 2015

Это не обязательно связано именно с вашей проблемой, но я публикую это, поскольку потратил пару дней, пытаясь исправить то же сообщение об ошибке в моем приложении. У нас есть приложение Java, использующее пул соединений C3P0, драйвер JTDS, подключающийся к базе данных SQL Server.

Мы отключили кэширование операторов в нашем пуле соединений C3P0, но не сделали этого на уровне драйвера. Добавление maxStatements = 0 к нашему URL-адресу соединения остановило операторы кэширования драйвера и исправило ошибку.

0 голосов
/ 03 сентября 2011

Сервер кэширует план запроса, когда вы вызываете 'command.Prepare'.Ошибка указывает, что он не может найти этот кэшированный план запроса при повторном вызове «Подготовка».Попробуйте создать новый экземпляр 'SqlCommand' и вызвать запрос к нему.Я уже сталкивался с этим исключением, и оно исправляется, когда сервер обновляет кэш.Я сомневаюсь, что есть что-нибудь, что можно сделать программно на стороне клиента, чтобы это исправить.

...