Почему мой SqlCommand возвращает строку, когда она должна быть ИНТ?

голоса
4

У меня есть запрос , который должен всегда быть возвращающимися один Int. Я теперь вошел его возвращающим строку целиком , не связанную с каким оно должно быть.

Мы получали несколько случайных FormatExceptions, что мы разыскали несколько запросов к базе данных. После некоторой дополнительной заготовки леса, я обнаружил, что, сегодня утром, запрос ниже возвращается строка «гладиатор». Website.PkID является ИНТ колонна и работает большую часть времени, но несколько раз он с треском проваливается и возвращает либо Int, что это Waaaay там (больше, чем любой действительный WebsiteID) или случайную строку.

Этот конкретный запрос ударил один раз в начале сеанса. Он не использует общую связь, поэтому у меня возникают проблемы с пониманием, как он мог бы получить такой растерянный результат. Может ли быть какая-то коррупция в пулы соединений?

Я не думаю, что проблема изолирована на этот запрос. Я видел подобные FormatExceptions (из-за неожиданный результат) исходя из запросов LINQ, а также. Мы также заметили некоторые из этих ошибок примерно в то же время:

Ошибка транспортного уровня произошла при отправке запроса на сервер. (Поставщик: поставщик TCP, ошибка: 0 - Существующее соединение было принудительно закрыто удаленным узлом.

Может ли это быть проблема подключения? Или, может быть, мы получаем результирующие наборы смешались между сервером БД и веб-сервер? Это действительно заставило меня чесать голову.

Оскорблять запрос:

public static int GetActiveWebSiteID(string storeID, string statusID)
{
    int retval;

    string sql = @SELECT isnull(MAX(PkID),0) FROM WebSite 
                   WHERE StoreID = @StoreID 
                   AND WebSiteStatusID = @WebSiteStatusID;

    SqlConnection conn = new SqlConnection(Settings.ConnString);
    SqlCommand cmd = new SqlCommand(sql, conn);
    cmd.CommandType = CommandType.Text;
    cmd.Parameters.AddWithValue(@StoreID, (object)storeID ?? DBNull.Value);
    cmd.Parameters.AddWithValue(@WebSiteStatusID, (object)statusID ?? DBNull.Value);

    conn.Open();
    using(conn)
    {
        var scalar = cmd.ExecuteScalar(); // <-- This value returned here should only ever be an int, but randomly is a string

        retval = Convert.ToInt32(scalar);
    }
    return retval;
}

Этот запрос не работал нормально в течение многих лет до недавнего времени. Теперь у нас есть куча дополнительных запросов LINQ в приложении (не уверен, если это имеет значение). Мы бежим .Net 3.5.

Задан 19/05/2009 в 12:33
источник пользователем
На других языках...                            


9 ответов

голоса
1

Функция ExecuteScalar () в возвращаемом типе object, и вы объявляете переменный результат с varключевым словом. Это не очень хорошая комбинация, потому что вы помещаете много давления в системе , чтобы получить вывод типа права.

Ответил 19/05/2009 в 12:58
источник пользователем

голоса
1

Я думаю , что вы думали о том, sqlCommand.ExecuteNonQueryчто возвращает количество строк в целочисленном значении ...

Это определение метода ExecuteScalar:

public override object ExecuteScalar()
Member of System.Data.SqlClient.SqlCommand

Резюме:

Выполняет запрос и возвращает первый столбец первой строки в наборе результатов , возвращаемого запросом. Дополнительные столбцы или строки игнорируются.

Возвращает:

Первый столбец первой строки в наборе результатов, или пустая ссылка (Nothing в Visual Basic), если результирующий набор пуст.

Таким образом, я думаю, что общий способ возвращения этого столбца как строковое представление значения столбца.

Ответил 19/05/2009 в 13:25
источник пользователем

голоса
0

Поле «PkID» является VARCHAR / символ в таблице «WebSite».

Если «ISNULL» часть запроса верно, то он будет возвращать целое число (0), в противном случае она возвращает строку со значением «PkID»

Ответил 19/05/2009 в 13:46
источник пользователем

голоса
0

Там может быть более чем один WebSite стол. Вы можете претендовать на таблицу с именем схемы:

ВЫБОР IsNull (МАКС (PkID), 0) ОТ YourSchema.WebSite ГДЕ StoreID = @StoreID И WebSiteStatusID = @WebSiteStatusID

Ответил 19/05/2009 в 14:56
источник пользователем

голоса
0

Есть ли общность, когда она не возвращает Int?

Так как ваш запрос только когда-либо возвращает один столбец в одной строке, что вы получите, если вы используете более типизированный ExecuteReader и принимаете значение первого столбца?

Всегда ли это возвращает строку? Если WHEREположение заставляет его не вернуть ни одной строки (скажем , ваши параметры не то , что вы думаете , что они есть), ваш ISNULLне вступит в силу - нет ни одной строки на всех, и ExecuteScalar должен возвращать NULL.

Ответил 19/05/2009 в 15:59
источник пользователем

голоса
1

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

Кроме того, ради здравомыслие, пожалуйста, используйте вложенные с использованием блоков, как:

using(SqlConnection conn = new SqlConnection("hard-coded connection string"))
{
    using (SqlCommand cmd = new SqlCommand(sql, conn))
    {
        // more init
        object scalar = cmd.ExecuteScalar();

        // process result
    }
 }

Это не удивило бы меня, чтобы найти там два экземпляра базы данных, и в одном, PkID является ИНТ, в другом это VARCHAR.


Посмотрите с SQL Profiler, чтобы увидеть, если вы можете поймать возвращение «гладиатор». В другом случае я работал с, SQL Profiler не показал вообще ничего, что указывает на фактический запрос собирается в другую базу данных.

Ответил 19/05/2009 в 16:09
источник пользователем

голоса
0

Я не думаю, что ни один ваш запрос отвечал ни LINQ являются проблемой.

Вы действительно уверены, что вы смотрите на право источника? Как метод называется? Как протоколирование сделано?

Выберите не нарушена.

Ответил 19/05/2009 в 16:12
источник пользователем

голоса
0

Я предполагаю, что Settings.ConnString считывается из Web.Config или реестра и повторно используются другие статические процедуры. Может быть, возможно, что существует проблема времени, когда второй метод выполняется до вызова cmd.ExecuteScalar () в рутине, которая модифицирует cmd.CommandText на связи?

Надеюсь это поможет,

Билл

Ответил 20/05/2009 в 15:45
источник пользователем

голоса
9

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

Мы наблюдали запросы в Profiler и были в состоянии видеть, что плохие результаты всегда были связаны с той же ИСП, и что каждый плохой результат всегда был один запрос за фактическое заявление SQL выполняется запрос. Это было похоже на набор результатов был пропустил и все, что результирующий набор был следующим в ИСП (от другого соединения в одном пуле) был возвращен. Псих.

Методом проб и ошибок, мы в конце концов выследили несколько запросов SqlCommand или LINQ, чьи SqlConnection не был закрыт сразу же после использования. Вместо этого через некоторое неаккуратное программирование, происходящее из непонимания соединений LINQ, объекты DataContext были расположены (и закрытые соединения) только в конце запроса, а не сразу.

После того, как мы переработаны эти методы , чтобы немедленно закрыть соединение с C # « используя» блок (высвобождая этот пул для следующего запроса), мы не получили никаких больше ошибок. Пока мы еще не знаем , основная причина , что пул соединений будет получить так перепутал, мы были в состоянии прекратить все ошибки этого типа. Эта проблема была решена в сочетании с другой подобной ошибки я вывесил, нашел здесь: Каковы причины «Внутреннее соединение Роковые ошибки»?

Ответил 22/09/2009 в 17:18
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more