Обработка ExecuteScalar(), когда результаты не возвращаются
Я использую следующий запрос SQL и метод ExecuteScalar()
для извлечения данных из базы данных Oracle:
sql = "select username from usermst where userid=2"
string getusername = command.ExecuteScalar();
Это показывает мне это сообщение об ошибке:
System.NullReferenceException: ссылка на объект не установлена на экземпляр объекта
Эта ошибка возникает, когда в таблице базы данных нет строки для userid=2
.
Как мне справиться с этой ситуацией?
Ответы
Ответ 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());