web-dev-qa-db-ja.com

結果が返されない場合のExecuteScalar()の処理

次のSQLクエリとExecuteScalar()メソッドを使用して、Oracleデータベースからデータを取得しています。

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

次のエラーメッセージが表示されます。

System.NullReferenceException:オブジェクト参照がオブジェクトのインスタンスに設定されていません

このエラーは、データベーステーブルにuserid=2の行がない場合に発生します。
この状況に対処するにはどうすればよいですか?

55
Hemant Kothiyal

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に割り当てられます。
  • 行は存在するが、ユーザー名にNULLがある場合(これはDBでも可能ですか?)、command.ExecuteScalar()の結果は_DBNull.Value_になり、InvalidCastExceptionになります。

いずれにせよ、NullReferenceExceptionは使用できないはずなので、問題はおそらく別の場所にあります。

51

まず、コマンドオブジェクトがnullでないことを確認する必要があります。次に、コマンドのCommandTextプロパティをSQLクエリに設定する必要があります。最後に、戻り値をオブジェクト変数に保存し、使用する前にnullかどうかを確認する必要があります。

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

VB構文についてはわかりませんが、アイデアは得られます。

48
Rune Grimstad

私はこれを使用しました:

    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;
    }
22
Fanda

次の行:

string getusername = command.ExecuteScalar();

...次のように、結果を暗黙的に文字列に変換しようとします。

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

オブジェクトがnullの場合、通常のキャスト演算子は失敗します。次のようにas-operatorを使用してみてください。

string getusername = command.ExecuteScalar() as string;
8
Tommy Carlier
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();
  }
}

これから こちら

6
jjj

SQL[〜#〜] null [〜#〜]

  • c#で同等なのはDBNull.Value
  • nULLABLE列に値がない場合、これが返されます
  • sQLでの比較:IF ( value IS NULL )
  • c#での比較:if (obj == DBNull.Value)
  • c#クイックウォッチで{}として視覚的に表される

データリーダーから読み取るときのベストプラクティス:

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));
3
Bizhan

行を読む前に、常に確認してください。

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

}
3
Sagar

これが最も簡単な方法です...

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
}
2
some_yahoo

または、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();
1
alkk
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();
        }

    }
1
SMA

あなたの場合、レコードがuserid=2で存在しないか、SQLコマンドで使用されるクエリ結果に値が見つからない場合、ExecuteScalar()が返されるため、最初の列にnull値が含まれる可能性がありますnull

1
MAX

この問題は、データベースに接続するユーザーにCONNECT権限があったが、データベースから読み取る権限がなかったときに発生しました。私の場合、このようなことすらできませんでした。

object userNameObj = command.ExecuteScalar()

これをtry/catchに配置する(おそらくとにかく行う必要があります)ことは、アクセス許可が不十分な問題を処理するための唯一の方法でした。

0
Freefall

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;
}
0
radbyx

私はVS2010で見ましたstring getusername = command.ExecuteScalar();はコンパイルエラーを与えます暗黙的に型オブジェクトを文字列に変換できません。したがって、データベースにレコードが見つからないときにエラーが発生する場合は、string getusername = command.ExecuteScalar().ToString();を記述する必要がありますオブジェクトのインスタンスに設定されていないオブジェクト参照で、「。 、エラーは発生しません。したがって、ExecuteScalarは例外をスローしないと言えます。 @Rune Grimstadからの回答は正しいと思います。

0
minu

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 ;
}
0
panky sharma

わずかな推測:スタックの例外をチェックすると、スタックがスローされ、OracleのADO.NETプロバイダーが基礎となる行セットを読み取って最初の値を取得します。

行がない場合、検索する値はありません。

この場合を処理するには、リーダーに対して実行し、一致しない場合にNext()がfalseを返すように処理します。

0
Richard