次のSQLクエリとExecuteScalar()
メソッドを使用して、Oracleデータベースからデータを取得しています。
sql = "select username from usermst where userid=2"
string getusername = command.ExecuteScalar();
次のエラーメッセージが表示されます。
System.NullReferenceException:オブジェクト参照がオブジェクトのインスタンスに設定されていません
このエラーは、データベーステーブルにuserid=2
の行がない場合に発生します。
この状況に対処するにはどうすればよいですか?
DbCommand.ExecuteScalarのMSDNドキュメント によると:
結果セットの最初の行の最初の列が見つからない場合、null参照(Visual BasicではNothing)が返されます。データベースの値がnullの場合、クエリは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になり、null文字列にキャストされてgetusername
に割り当てられます。command.ExecuteScalar()
の結果は_DBNull.Value
_になり、InvalidCastException
になります。いずれにせよ、NullReferenceException
は使用できないはずなので、問題はおそらく別の場所にあります。
まず、コマンドオブジェクトがnullでないことを確認する必要があります。次に、コマンドのCommandTextプロパティをSQLクエリに設定する必要があります。最後に、戻り値をオブジェクト変数に保存し、使用する前にnullかどうかを確認する必要があります。
command = new OracleCommand(connection)
command.CommandText = sql
object userNameObj = command.ExecuteScalar()
if (userNameObj != null)
string getUserName = userNameObj.ToString()
...
VB構文についてはわかりませんが、アイデアは得られます。
私はこれを使用しました:
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;
}
次の行:
string getusername = command.ExecuteScalar();
...次のように、結果を暗黙的に文字列に変換しようとします。
string getusername = (string)command.ExecuteScalar();
オブジェクトがnullの場合、通常のキャスト演算子は失敗します。次のようにas-operatorを使用してみてください。
string getusername = command.ExecuteScalar() as string;
sql = "select username from usermst where userid=2"
var _getusername = command.ExecuteScalar();
if(_getusername != DBNull.Value)
{
getusername = _getusername.ToString();
}
これは役立つかもしれません..例::
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();
}
}
これから こちら
SQL[〜#〜] null [〜#〜]値
IF ( value IS NULL )
if (obj == DBNull.Value)
{}
として視覚的に表されるデータリーダーから読み取るときのベストプラクティス:
var reader = cmd.ExecuteReader();
...
var result = (reader[i] == DBNull.Value ? "" : reader[i].ToString());
私の経験では、戻り値が欠落している可能性があり、そのため、nullを返すことで実行が失敗する場合があります。例は
select MAX(ID) from <table name> where <impossible condition>
上記のスクリプトは、MAXを見つけるために何も見つけることができません。したがって、失敗します。このような場合、古い方法を比較する必要があります(C#null
と比較してください)
var obj = cmd.ExecuteScalar();
var result = (obj == null ? -1 : Convert.ToInt32(obj));
行を読む前に、常に確認してください。
if (SqlCommand.ExecuteScalar() == null)
{
}
これが最も簡単な方法です...
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
}
または、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();
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();
}
}
あなたの場合、レコードがuserid=2
で存在しないか、SQLコマンドで使用されるクエリ結果に値が見つからない場合、ExecuteScalar()
が返されるため、最初の列にnull値が含まれる可能性がありますnull
。
この問題は、データベースに接続するユーザーにCONNECT権限があったが、データベースから読み取る権限がなかったときに発生しました。私の場合、このようなことすらできませんでした。
object userNameObj = command.ExecuteScalar()
これをtry/catchに配置する(おそらくとにかく行う必要があります)ことは、アクセス許可が不十分な問題を処理するための唯一の方法でした。
string
またはempty string
何かがnullの場合、何も壊さないで:
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;
}
私はVS2010で見ましたstring getusername = command.ExecuteScalar();
はコンパイルエラーを与えます暗黙的に型オブジェクトを文字列に変換できません。したがって、データベースにレコードが見つからないときにエラーが発生する場合は、string getusername = command.ExecuteScalar().ToString();
を記述する必要がありますオブジェクトのインスタンスに設定されていないオブジェクト参照で、「。 、エラーは発生しません。したがって、ExecuteScalar
は例外をスローしないと言えます。 @Rune Grimstadからの回答は正しいと思います。
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 ;
}
わずかな推測:スタックの例外をチェックすると、スタックがスローされ、OracleのADO.NETプロバイダーが基礎となる行セットを読み取って最初の値を取得します。
行がない場合、検索する値はありません。
この場合を処理するには、リーダーに対して実行し、一致しない場合にNext()
がfalseを返すように処理します。