Подтвердить что ты не робот

Обработка ExecuteScalar(), когда результаты не возвращаются

Я использую следующий запрос SQL и метод ExecuteScalar() для извлечения данных из базы данных Oracle:

sql = "select username from usermst where userid=2"
string getusername = command.ExecuteScalar();

Это показывает мне это сообщение об ошибке:

System.NullReferenceException: ссылка на объект не установлена на экземпляр объекта

Эта ошибка возникает, когда в таблице базы данных нет строки для userid=2.
Как мне справиться с этой ситуацией?

4b9b3361

Ответ 1

Согласно документации MSDN для DbCommand.ExecuteScalar:

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

Рассмотрим следующий фрагмент:

using (var conn = new OracleConnection(...)) {
    conn.Open();
    var command = conn.CreateCommand();
    command.CommandText = "select username from usermst where userid=2";
    string getusername = (string)command.ExecuteScalar();
}

Во время выполнения (проверено в ODP.NET, но должно быть одинаковым в любом провайдере ADO.NET), оно ведет себя так:

  • Если строка не существует, результат command.ExecuteScalar() имеет значение null, которое затем преобразуется в нулевую строку и присваивается getusername.
  • Если строка существует, но имеет имя NULL в имени пользователя (возможно ли это даже в вашей БД?), Результатом команды command.ExecuteScalar() является DBNull.Value, что приводит к InvalidCastException.

В любом случае NullReferenceException не должно быть возможным, поэтому ваша проблема, вероятно, кроется в другом месте.

Ответ 2

Сначала вы должны убедиться, что ваш командный объект не является нулевым. Затем вы должны установить свойство CommandText команды для вашего SQL-запроса. Наконец, вы должны сохранить возвращаемое значение в объектной переменной и проверить, является ли оно пустым, прежде чем использовать его:

command = new OracleCommand(connection)
command.CommandText = sql
object userNameObj = command.ExecuteScalar()
if (userNameObj != null)
  string getUserName = userNameObj.ToString()
 ...

Я не уверен насчет синтаксиса VB, но вы поняли идею.

Ответ 3

Я просто использовал это:

    int? ReadTerminalID()
    {
        int? terminalID = null;

        using (FbConnection conn = connManager.CreateFbConnection())
        {
            conn.Open();
            FbCommand fbCommand = conn.CreateCommand();
            fbCommand.CommandText = "SPSYNCGETIDTERMINAL";
            fbCommand.CommandType = CommandType.StoredProcedure;

            object result = fbCommand.ExecuteScalar(); // ExecuteScalar fails on null
            if (result.GetType() != typeof(DBNull))
            {
                terminalID = (int?)result;
            }
        }

        return terminalID;
    }

Ответ 4

Следующая строка:

string getusername = command.ExecuteScalar();

... попытается неявно преобразовать результат в строку, как показано ниже:

string getusername = (string)command.ExecuteScalar();

Регулярный оператор литья будет терпеть неудачу, если объект имеет значение null. Попробуйте использовать as-operator, например:

string getusername = command.ExecuteScalar() as string;

Ответ 5

sql = "select username from usermst where userid=2"
var _getusername = command.ExecuteScalar();
if(_getusername != DBNull.Value)
{
    getusername = _getusername.ToString();
}  

Ответ 6

это может помочь.. пример::

using System;
using System.Data;
using System.Data.SqlClient;

class ExecuteScalar
{
  public static void Main()
  {
    SqlConnection mySqlConnection =new SqlConnection("server=(local)\\SQLEXPRESS;database=MyDatabase;Integrated Security=SSPI;");
    SqlCommand mySqlCommand = mySqlConnection.CreateCommand();
    mySqlCommand.CommandText ="SELECT COUNT(*) FROM Employee";
    mySqlConnection.Open();

    int returnValue = (int) mySqlCommand.ExecuteScalar();
    Console.WriteLine("mySqlCommand.ExecuteScalar() = " + returnValue);

    mySqlConnection.Close();
  }
}

из здесь

Ответ 7

Всегда проверяйте перед чтением строки.

if (SqlCommand.ExecuteScalar() == null)
{ 

}

Ответ 8

Значение SQL NULL

  • эквивалентом в С# является DBNull.Value
  • если столбец NULLABLE не имеет значения, это то, что возвращается
  • сравнение в SQL: IF ( value IS NULL )
  • сравнение в С#: if (obj == DBNull.Value)
  • визуально представлен в С# Quick-Watch как {}

Лучшая практика при чтении из устройства чтения данных:

var reader = cmd.ExecuteReader();
...
var result = (reader[i] == DBNull.Value ? "" : reader[i].ToString());

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

select MAX(ID) from <table name> where <impossible condition>

Приведенный выше скрипт не может найти ничего, чтобы найти MAX. Таким образом, он терпит неудачу. В таких случаях мы должны сравнивать старый способ (сравнить с С# null)

var obj = cmd.ExecuteScalar();
var result = (obj == null ? -1 : Convert.ToInt32(obj));

Ответ 9

В вашем случае либо запись не существует с userid=2, либо может содержать нулевое значение в первом столбце, потому что если для результата запроса, используемого в команде SQL, не найдено значения, ExecuteScalar() возвращает null.

Ответ 10

Это самый простой способ сделать это...

sql = "select username from usermst where userid=2"
object getusername = command.ExecuteScalar();
if (getusername!=null)
{
    //do whatever with the value here
    //use getusername.toString() to get the value from the query
}

Ответ 11

В качестве альтернативы вы можете использовать DataTable, чтобы проверить, есть ли строка:

SqlCommand cmd = new SqlCommand("select username from usermst where userid=2", conn);
SqlDataAdapter adp = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
adp.Fill(dt);
string getusername = "";
// assuming userid is unique
if (dt.Rows.Count > 0)
    getusername = dt.Rows[0]["username"].ToString();

Ответ 12

private static string GetUserNameById(string sId, string connStr)
    {
        System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(connStr);
        System.Data.SqlClient.SqlCommand command;

        try
        {
            // To be Assigned with Return value from DB
            object getusername;

            command = new System.Data.SqlClient.SqlCommand();

            command.CommandText = "Select userName from [User] where userid = @userid";

            command.Parameters.AddWithValue("@userid", sId);

            command.CommandType = CommandType.Text;

            conn.Open();

            command.Connection = conn;

            //Execute
            getusername = command.ExecuteScalar();

            //check for null due to non existent value in db and return default empty string
            string UserName = getusername == null ? string.Empty : getusername.ToString();

            return UserName;


        }
        catch (Exception ex)
        {

            throw new Exception("Could not get username", ex);
        }
        finally
        {
            conn.Close();
        }

    }

Ответ 13

Незначительная гипотеза: если вы проверяете стек для исключения, он бросается, а поставщик ADO.NET для Oracle читает базовый набор строк, чтобы получить первое значение.

Если строки нет, тогда нет значения для поиска.

Чтобы обработать этот случай, выполните для чтения и обработайте Next(), возвращая false для случая без соответствия.

Ответ 14

Я использую его как это с помощью библиотеки приложений Microsoft Application Block DLL (ее справочная библиотека для операций DAL)

public string getCopay(string PatientID)
{
       string sqlStr = "select ISNULL(Copay,'') Copay from Test where patient_id=" + PatientID ;
        string strCopay = (string)SqlHelper.ExecuteScalar(CommonCS.ConnectionString, CommandType.Text, sqlStr);
                if (String.IsNullOrEmpty(strCopay))
                    return "";
                else
                    return strCopay ;
}

Ответ 15

Я видел в VS2010 string getusername = command.ExecuteScalar(); дает ошибку компиляции, Невозможно неявно преобразовать объект типа в строку. Поэтому вам нужно написать string getusername = command.ExecuteScalar().ToString(); когда в базе данных нет записи, она дает ошибку В экземпляре объекта не задана ссылка на объект и когда я комментирую '.ToString()', это не дает никакой ошибки. Поэтому я могу сказать, что ExecuteScalar не выбрасывает исключение. Я думаю, что андервер, данный @Rune Grimstad, прав.

Ответ 16

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

object userNameObj = command.ExecuteScalar()

Помещая это в try/catch (который вы, вероятно, должны делать в любом случае), был единственным способом, с помощью которого я мог справиться с недостаточной проблемой разрешения.

Ответ 17

Если вы хотите либо string либо empty string в случае, если что-то равно нулю, без чего-либо может произойти разрыв:

using (var cmd = new OdbcCommand(cmdText, connection))
{
    var result = string.Empty;
    var scalar = cmd.ExecuteScalar();
    if (scalar != DBNull.Value) // Case where the DB value is null
    {
        result = Convert.ToString(scalar); // Case where the query doesn't return any rows. 
        // Note: Convert.ToString() returns an empty string if the object is null. 
                 It doesn't break, like scalar.ToString() would have.
    }
    return result;
}

Ответ 18

/* Выберите некоторый int, который не существует */ int x = ((int) (SQL_Cmd.ExecuteScalar()?? 0));

Ответ 19

Я использовал это в своем VB-коде для возвращаемого значения функции:

Если obj < > Nothing Then   Возврат obj.ToString()  еще   Вернуть ""  End If

Ответ 20

Попробуйте этот код, он, похоже, решит вашу проблему.

Dim MaxID As Integer = Convert.ToInt32(IIf(IsDBNull(cmd.ExecuteScalar()), 1, cmd.ExecuteScalar()))

Ответ 21

Я использую Oracle. Если ваш sql возвращает числовое значение, которое является int, вам нужно использовать Convert.ToInt32 (объект). Ниже приведен пример:

public int GetUsersCount(int userId)
{
    using (var conn = new OracleConnection(...)){
        conn.Open();
        using(var command = conn.CreateCommand()){
            command.CommandText = "select count(*) from users where userid = :userId";
            command.AddParameter(":userId", userId);            
            var rowCount = command.ExecuteScalar();
            return rowCount == null ? 0 : Convert.ToInt32(rowCount);
        }
    }
}

Ответ 22

Попробуйте это

sql = "select username from usermst where userid=2"

string getusername = Convert.ToString(command.ExecuteScalar());