С# ExecuteScalar()

Я пытаюсь создать игру в кости, хранить данные о пользователях/игре и т. д. В этой задаче я пытаюсь проверить, занято ли уже имя пользователя. Но по какой-то причине, независимо от того, как я пытаюсь объявить свою переменную для получения результата ExecuteScalar(), я всегда получаю сообщение об ошибке «Невозможно преобразовать из nVarChar в int».

private bool CheckForUser()
{
        //returns true if Username is already registered
        SqlConnection connection = new SqlConnection("...");
        string query = "SELECT * FROM Users WHERE USERID = @alias";
        SqlCommand cmd = new SqlCommand(query, connection);
        cmd.Parameters.AddWithValue("@alias", tbNewUsername.Text);
        connection.Open();
        Object DbResult = cmd.ExecuteScalar(); //<-ERROR
        connection.Close();
        DbResult = (DbResult == DBNull.Value) ? null : DbResult;

        if (DbResult != null)
            return true;
        else
            return false;

}

Это была моя последняя попытка перед поиском помощи. Приведение к типу int не работает, строка не работает, а объявление DbResult как объекта не работает. Я понимаю, почему его нельзя преобразовать в int, но я не знаю, почему он продолжает попытки.

Спасибо за любую помощь.


person Jacob Hill    schedule 20.10.2018    source источник
comment
Вот почему это дубликат: вы передаете string параметру с AddWithValue, который предполагает, что параметр является NVARCHAR, когда он должен быть int (согласно USERID). Используйте cmd.Parameters.Add("alias", DbType.Int32).Value = tbNewUsername.Text; (или что-то подобное, у меня нет открытого VS)   -  person Camilo Terevinto    schedule 21.10.2018
comment
Я нашел это. SELECT * FROM Users WHERE USERID = @alias Вы сравниваете идентификатор пользователя (целочисленный первичный ключ) со строковым вводом. Очень помогло бы, если бы вы указали, была ли это ошибка времени компиляции или времени выполнения :) Тем не менее, я настаиваю на необходимости изменить это.   -  person Christopher    schedule 21.10.2018


Ответы (2)


Выполнение такой проверки в графическом интерфейсе, а не в БД, вероятно, является плохой идеей. Таким образом вы столкнетесь только с условиями гонки. Обычно вы:

  • Настройте таблицу так, чтобы разрешались только уникальные (логин) имена.
  • попробуйте вставить конкретного нового пользователя
  • вставка либо терпит неудачу, либо не терпит неудачу

Такие вещи, как информирование регистрирующегося пользователя о том, что имя уже занято? Это дополнительная функция качества жизни для пользовательского интерфейса регистрации, а не основная вещь.

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

Изменить. Другая проблема заключается в том, что вы не удаляете соединение. Это вызовет у вас проблемы. вы всегда должны применять шаблон использования с сетевыми подключениями и доступом к файлам. И все остальное, что реализует IDisposeable.

person Christopher    schedule 20.10.2018
comment
Кто продолжает минусовать меня без какой-либо информации о том, что я делаю неправильно? При репутации чуть меньше 2000 я думаю, что заслуживаю хотя бы объяснения. - person Christopher; 21.10.2018
comment
Прочтите мой комментарий под вопросом, чтобы понять, почему кто-то возможно проголосовал против вас. - person Camilo Terevinto; 21.10.2018
comment
@CamiloTerevinto: Кто не согласен с Race Condition для проверки вашего кода? какие другие надежные варианты существуют для проверки условий гонки при доступе к БД? - person Christopher; 21.10.2018
comment
может быть не из-за этого, а из-за ошибки компилятора (их нет), предположения, что систему использует более 1 пользователя и т.д. Или вполне может быть из-за того, что кто-то не как и вы, мы не можем знать :) - person Camilo Terevinto; 21.10.2018

Вы смотрели примеры на Майкрософт? У них есть следующий пример, в котором рассказывается, как использовать функцию ExecuteScalar и какой тип возврата следует ожидать:

cmd.CommandText = "SELECT COUNT(*) FROM dbo.region";  
Int32 count = (Int32) cmd.ExecuteScalar();  
person Mark    schedule 20.10.2018
comment
Хотя это хороший общий ответ, на самом деле это не решает проблему. В частности, как Object DbResult = cmd.ExecuteScalar(); //<-ERROR может дать Невозможно преобразовать из nVarChar в int как предупреждение компилятора. Насколько я могу судить, он все делает правильно в этом фрагменте кода. - person Christopher; 21.10.2018