ExecuteNonQuery() всегда возвращает -1

Я создаю приложение для входа в систему с С# и SQL Server.

Что делает моя программа: проверяет, можно ли найти заданное имя пользователя и пароль в базе данных.

Если его можно найти, ExecuteNonQuery() должен вернуть 1 (найдена 1 строка).

Если комбинация не существует, ExecuteNonQuery() должна вернуть что-то еще.

Но в моем случае всякий раз, когда я использую хорошую или неправильную комбинацию, она всегда возвращает -1... как мне это исправить?

Я знаю, есть несколько существующих сообщений по тому же вопросу, но это все еще не исправлено...

Кроме того, в чем разница между ExecuteNonQuery() и ExecuteScalar()?

Это запрос, который отправляется:

private void btn_loginvolgende_Click(object sender, EventArgs e)
{
    gebruiker.Gebruikersnaam = Convert.ToString(tb_gebruikersnaamlogin.Text);
    gebruiker.Wachtwoord = Convert.ToString(tb_wachtwoordlogin.Text);
    gebruiker.Achternaam = "a";
    gebruiker.Geslacht = "a";
    gebruiker.Geslacht = "a";
    gebruiker.Huidiggewicht = 1;
    gebruiker.Streefgewicht = 1;
    gebruiker.Leeftijd = 1;
    gebruiker.Naam = "a";

    db.QueryToDatabase("Select count (*) from Gebruiker where Wachtwoord = @Wachtwoord AND Gebruikersnaam = @Gebruikersnaam;", gebruiker);
    Thread.Sleep(500);

    if (db.Success == false)
    {
        MessageBox.Show("Login gegevens kloppen niet!");
    }
    else if (db.Success == true)
    {
        MessageBox.Show("U bent met succes ingelogd");
    }
}

и это мой класс:

public void QueryToDatabase(string commandText, Gebruikerklasse gebruiker)
{
    // nieuwe connectie maken
    // ontvangt de query vanuit 'buttonclick' en voert hem hier uit
    // als ExecuteNonQuery niet kan worden uitgevoerd is er iets fout gegaan. D.m.v een bool moet hij dan een bericht tonen
    using (SqlConnection conn = new SqlConnection(connectionString))
    using (SqlCommand cmd = new SqlCommand(commandText, conn))
    {
        conn.Open();

        cmd.Parameters.AddWithValue("@Naam", gebruiker.Naam);
        cmd.Parameters.AddWithValue("@Achternaam", gebruiker.Achternaam);
        cmd.Parameters.AddWithValue("@Leeftijd", gebruiker.Leeftijd);
        cmd.Parameters.AddWithValue("@Geslacht", gebruiker.Geslacht);
        cmd.Parameters.AddWithValue("@Huidiggewicht", gebruiker.Huidiggewicht);
        cmd.Parameters.AddWithValue("@Streefgewicht", gebruiker.Streefgewicht);
        cmd.Parameters.AddWithValue("@Gebruikersnaam", gebruiker.Gebruikersnaam);
        cmd.Parameters.AddWithValue("@Wachtwoord", gebruiker.Wachtwoord);

        int a = cmd.ExecuteNonQuery();

        if (a == 1)
        {
            Success = true;
        }
        else if (a == -1)
        {
            Success = false;
        }

        conn.Close();
    }
}

person Cihan Kurt    schedule 06.01.2017    source источник
comment
Вы выполняете запрос SELECT. ExecuteNonQuery возвращает количество затронутых строк при выполнении UPDATE/INSERT/DELETE. Если вы хотите узнать, есть ли у вас запись, используйте ExecuteReader и проверьте, имеет ли возвращенный объект HasRows   -  person Steve    schedule 07.01.2017
comment
из msdn, для операторов UPDATE, INSERT и DELETE возвращаемое значение — это количество строк, затронутых командой. Если для вставляемой или обновляемой таблицы существует триггер, возвращаемое значение включает в себя количество строк, затронутых операцией вставки или обновления, и количество строк, затронутых триггером или триггерами. Для всех остальных типов операторов возвращаемое значение равно -1. Если происходит откат, возвращаемое значение также равно -1.   -  person Shyju    schedule 07.01.2017
comment
Выглядит лучше, этот запрос должен выполняться ExecuteScalar, потому что в результате у вас есть одна строка с одним столбцом.   -  person Steve    schedule 07.01.2017
comment
Я использую тот же метод для регистрации. Мне нужно выполнить nonquery для этого. Но вы предлагаете мне сделать другой способ входа в систему? Так что я могу использовать ExecuteReader?   -  person Cihan Kurt    schedule 07.01.2017
comment
Кажется, вы хотите, чтобы один метод выполнял все возможные задачи с базой данных. Это практически невозможно. Лучший подход — иметь в классе специальные методы, которые взаимодействуют с базой данных.   -  person Steve    schedule 07.01.2017
comment
Предупреждения об опечатках: это запрос (всего одного r достаточно!), но, с другой стороны, это Успех два s в конце) - и это относится к нескольким вашим вопросам в последнее время....   -  person marc_s    schedule 08.01.2017


Ответы (2)


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

Например, вы можете изменить свой Gebruikerklasse и добавить метод под названием Exists, где вы сможете точно настроить взаимодействие для конкретной задачи. Не нужно создавать много параметров, когда нужно всего два. Используйте более производительный вызов ExecuteScalar (и правильный), чтобы вернуть информацию из хранилища и т. д....

public class Gebruikerklasse 
{
    ....
    public bool Exists()
    {
        string commandText = @"Select count (*) from Gebruiker 
                              where Wachtwoord = @Wachtwoord AND 
                             Gebruikersnaam = @Gebruikersnaam;", 
        using (SqlConnection conn = new SqlConnection(DBClass.GetConnectionString()))
        using (SqlCommand cmd = new SqlCommand(commandText, conn))
        {
            conn.Open();
            cmd.Parameters.AddWithValue("@Gebruikersnaam", gebruiker.Gebruikersnaam);
            cmd.Parameters.AddWithValue("@Wachtwoord", gebruiker.Wachtwoord);
            int a = Convert.ToInt32(cmd.ExecuteScalar());
            return (a > 0);
        }
    }
}

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

Боковое примечание: принудительный подсчет таблицы только для того, чтобы узнать, существует ли запись или нет, является пустой тратой времени. Здесь очень помогает специальный оператор SQL.
Найдите IF EXISTS и прочитайте эту статью
Exists vs Count Битва никогда не заканчивается

person Steve    schedule 06.01.2017
comment
var a = (int) cmd.ExecuteScalar(); если (a › 0) { Успех = истина; } еще { успех = ложь; } Это сработало! Спасибо! Как-то неловко задавать здесь такие "глупые" вопросы... - person Cihan Kurt; 07.01.2017
comment
Ну, это одно и то же, но поскольку приведенный выше код находится в другом классе, вероятно, свойство Success отсутствует. - person Steve; 07.01.2017

Я знаю, что на этот вопрос был дан ответ. Но я хотел бы добавить некоторую дополнительную информацию для вас:

ExecuteNonQuery — выполняет запрос и возвращает затронутые строки.

ExecuteScalar — выполняет запрос и возвращает значение первого столбца первой строки.

ExecuteReader — выполняет запрос и возвращает SqlDataReader; который можно использовать для чтения запрошенных записей базы данных

Недавно я также написал учебник по этому вопросу, включая «управление памятью». См.: http://jeroenstevens.blogspot.ca/2017/02/how-to-connect-netc-to-sql-database.html

person Jeroen Stevens    schedule 08.02.2017