私はそれが以下のコードでうまく機能するデータベースから最初の行の最初のセル値を取得したいです。ただし、結果が見つからない場合は、例外がスローされます。
DBNull
で処理する方法。
クエリを変更する必要がありますか?記録がない場合に値を返すのはどれですか?
System.NullReferenceException:オブジェクト参照がオブジェクトのインスタンスに設定されていません。
コード:
public string absentDayNo(DateTime sdate, DateTime edate, string idemp)
{
string result="0";
string myQuery="select COUNT(idemp_atd) absentDayNo from td_atd where ";
myQuery +=" absentdate_atd between '"+sdate+"' and '"+edate+" ";
myQuery +=" and idemp_atd='"+idemp+"' group by idemp_atd ";
SqlCommand cmd = new SqlCommand(myQuery, conn);
conn.Open();
//System.NullReferenceException occurs when their is no data/result
string getValue = cmd.ExecuteScalar().ToString();
if (getValue != null)
{
result = getValue.ToString();
}
conn.Close();
return result;
}
getValue
はすでに文字列であるため、.ToString()
を呼び出し続ける必要はありません。
それとは別に、この行はおそらくあなたの問題かもしれません:
string getValue = cmd.ExecuteScalar().ToString();
行がない場合、.ExecuteScalar
はnull
を返すため、チェックを行う必要があります。
例えば:
var firstColumn = cmd.ExecuteScalar();
if (firstColumn != null) {
result = firstColumn.ToString();
}
返される最初のセルがnull
の場合、.NETの結果はDBNull.Value
になります
セルが返されないの場合、.NETの結果はnull
になります。 null
でToString()
を呼び出すことはできません。もちろん、ExecuteScalar
が返すものをキャプチャし、null
/DBNull
/その他のケースを個別に処理できます。
グループ化などをしているので、おそらく複数のグループを持つ可能性があります。率直に言って、ExecuteScalar
がここでの最良の選択肢かどうかわかりません...
追加:質問のSQLは多くの点で悪いです:
パラメータ化することを強くお勧めします。たぶんそれを簡単にするための「dapper」のようなものを使って:
int count = conn.Query<int>(
@"select COUNT(idemp_atd) absentDayNo from td_atd
where absentdate_atd between @sdate and @edate
and idemp_atd=@idemp group by idemp_atd",
new {sdate, edate, idemp}).FirstOrDefault();
「行なし」シナリオを含むすべての問題が解決されました。日付は(文字列ではなく)日付として渡されます。注入口はパラメータを使用して閉じられます。追加のボーナスとしてクエリプランの再利用もできます。ここでgroup by
は冗長です、ところで-グループが1つしかない場合(等価条件を介して)、COUNT(1)
を選択するだけでもかまいません。
これを試して
var getValue = cmd.ExecuteScalar();
conn.Close();
return (getValue == null) ? string.Empty : getValue.ToString();
次のように使用できます
string result = null;
object value = cmd.ExecuteScalar();
if (value != null)
{
result = value.ToString();
}
conn.Close();
return result;
値はnullではなく、DBNull.Valueです。
object value = cmd.ExecuteScalar();
if(value == DBNull.Value)
これを試して :
string getValue = Convert.ToString(cmd.ExecuteScalar());
これは動作するはずです:
var result = cmd.ExecuteScalar();
conn.Close();
return result != null ? result.ToString() : string.Empty;
また、クエリでパラメーターを使用することをお勧めします(次のような提案です)。
var cmd = new SqlCommand
{
Connection = conn,
CommandType = CommandType.Text,
CommandText = "select COUNT(idemp_atd) absentDayNo from td_atd where absentdate_atd between @sdate and @edate and idemp_atd=@idemp group by idemp_atd"
};
cmd.Parameters.AddWithValue("@sdate", sdate);
cmd.Parameters.AddWithValue("@edate", edate);
// etc ...
SQLサーバーのisnull関数を使用する
public string absentDayNo(DateTime sdate, DateTime edate, string idemp)
{
string result="0";
string myQuery="select isnull(COUNT(idemp_atd),0) as absentDayNo from td_atd where ";
myQuery +=" absentdate_atd between '"+sdate+"' and '"+edate+" ";
myQuery +=" and idemp_atd='"+idemp+"' group by idemp_atd ";
SqlCommand cmd = new SqlCommand(myQuery, conn);
conn.Open();
//System.NullReferenceException occurs when their is no data/result
string getValue = cmd.ExecuteScalar().ToString();
if (getValue != null)
{
result = getValue.ToString();
}
conn.Close();
return result;
}
C#の高度な機能があり、その「?」を使用します。 。 string getValue = cmd.ExecuteScalar()?. ToString();すべてに感謝します。