Как использовать ExecuteScalar с хранимой процедурой? - PullRequest
0 голосов
/ 13 декабря 2018

Я пытаюсь получить количество записей столбцов в базе данных Sql и показать результат в MessageBox.

Это мой код:

public DataTable CheckIfNameExist(string name)
{
    con = Connect();
    cmd = new SqlCommand();
    cmd.Connection = con;
    cmd.CommandText = "spCheckIfNameExist";
    cmd.Parameters.AddWithValue("@Name", SqlDbType.NVarChar).Value = name;
    MessageBox.Show(name);

    Int32 totalNames = (Int32) cmd.ExecuteScalar();
    string tNames = totalNames.ToString();

    MessageBox.Show(tNames);
}

А это мой sp:

@Name nvarchar(50) = null
As
Begin
SELECT COUNT(*) from OrdersSent where CustomerName LIKE @Name + '%'
End

Проблема:

Всегда возвращает 0.

Ответы [ 3 ]

0 голосов
/ 13 декабря 2018

У вас есть несколько проблем в коде c #, вероятно, наиболее важными являются следующие:

cmd.Parameters.AddWithValue("@Name", SqlDbType.NVarChar).Value = name;

Не используйте AddWithValue. Используйте Add.

Кроме того, вы не указали тип команды - по умолчанию это Text.
И вы используете поля для SqlConnection и SqlCommand - что тоже неправильно.Вы должны создать и расположить их обоих внутри каждого метода, который вы используете.

Лучшая версия вашего кода была бы такой:

using(var con = new SqlConnection(ConnectionString))
{
    using(var cmd = new SqlCommand("spCheckIfNameExist", con))
    {
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add("@Name", SqlDbType.NVarChar).Value = name;
        con.Open();
        var tNames = cmd.ExecuteScalar().ToString();
    }
}

Еще одна вещь, которая озадачивает меня, - это почему методВызванный CheckIfNameExist возвращает DataTable.Я ожидаю, что он просто вернет bool.

Если вы действительно хотите проверить, существует ли имя, вы можете сделать это лучше как на уровне SQL, так и на уровне c #.

Лучше SQL будет выглядеть примерно так:

SELECT CAST(CASE WHEN EXISTS(
    SELECT 1 
    FROM OrdersSent 
    WHERE CustomerName LIKE @Name + '%'
) THEN 1 ELSE 0 END AS bit)

А на уровне c # бит переводится непосредственно в bool, поэтому код может быть простым:

public bool CheckIfNameExist(string name)
{
    using(var con = new SqlConnection(ConnectionString))
    {
        using(var cmd = new SqlCommand("spCheckIfNameExist", con))
        {
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Add("@Name", SqlDbType.NVarChar).Value = name;
            con.Open();
            return (bool)cmd.ExecuteScalar();
        }
    }
}

И ещепримечание: вам следует избегать использования префикса sp для хранимых процедур.
Microsoft зарезервировала этот префикс для встроенных системных процедур.Для получения дополнительной информации прочитайте Аарона Бертранда. Префикс sp_ по-прежнему запрещен? , где вы увидите, что краткий ответ на этот вопрос "Да".

Префикс sp_ не означает, что вы думаете, что он делает: большинство людей думают, что sp означает «хранимая процедура», хотя на самом деле это означает «особый».Хранимые процедуры (а также таблицы и представления), хранящиеся в master с префиксом sp_, доступны из любой базы данных без надлежащей ссылки (при условии, что локальная версия не существует).Если процедура помечена как системный объект (с помощью sp_MS_marksystemobject (недокументированная и неподдерживаемая системная процедура, которая устанавливает is_ms_shipped в 1), то процедура в master будет выполняться в контексте вызывающей базы данных.

0 голосов
/ 13 декабря 2018

В вашем коде есть пара ошибок: вы должны написать его следующим образом:

cmd.CommandText = "spCheckIfNameExist";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@Name", SqlDbType.NVarChar).Value = name;

Сначала вы должны сообщить механизму ADO, что вы вызываете хранимую процедуру, а не простой текст команды,но вам также нужно использовать Add вместо AddWithValue, чтобы точно указать тип параметра, передаваемого SP.Ваш код создает параметр int, потому что второй параметр AddWithValue - это значение параметра, а не его тип.

0 голосов
/ 13 декабря 2018

Вам необходимо указать тип вашей команды следующим образом:

cmd.CommandText = "spCheckIfNameExist";
cmd.CommandType = CommandType.StoredProcedure;

См. Также:

В чем преимущество использования CommandType.StoredProcedure по сравнению с использованием CommandType.Text?

Хотя указывать тип напрямую и использовать свойство Value лучше, чем AddWithValue:

cmd.Parameters.Add("@Name", SqlDbType.NVarChar).Value = name;

Следующая статья также может быть интересной:

https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/

...