C#でデータベースから取得したレコードのフィールドのNULLを検出するコードを紹介します。
下記のテーブルを作成します。
id=3のレコードはcategory列の値がNULLになっています。
列名 | 型 |
---|---|
id | int |
name | nchar(64) |
value | decimal(18,0) |
category | nchar(16) |
memo | text |
id | name | value | category | memo |
---|---|---|---|---|
1 | Penguin | 300 | B | 南国にすむペンギンです |
2 | Whale | 420 | M | 北極海のクジラです |
3 | Moffu | 880 | NULL | よくわからない生き物です |
4 | Camel | 220 | M | 砂漠にすむラクダです |
5 | Owl | 90 | B | 関東のフクロウです |
6 | Duck | 120 | B | そこらへんのアヒルです |
下図のUIを作成します。テキストボックスとボタンを配置します。
下記のコードを記述します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace SQLExecDemo
{
public partial class FormSQLNull : Form
{
public FormSQLNull()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string constr = @"Data Source=192.168.64.98;Initial Catalog=iPentecSandBox;Connect Timeout=60;Persist Security Info=True;User ID=sa;Password=adelieC#8851SQL";
SqlConnection con = new SqlConnection(constr);
con.Open();
try {
string sqlstr = "select * from working";
SqlCommand com = new SqlCommand(sqlstr, con);
SqlDataReader sdr = com.ExecuteReader();
while (sdr.Read() == true) {
string name = (string)sdr["name"];
decimal value = (decimal)sdr["value"];
string category = (string)sdr["category"];
string memo = (string)sdr["memo"];
textBox1.Text += string.Format("{0} / {1:g} / {2} / {3} \r\n",
name.Trim(), value, category.Trim(), memo.Trim());
}
}
finally {
con.Close();
}
}
}
}
プロジェクトを実行します。下図のウィンドウが表示されます。
[button1]をクリックすると、InvalidCastException 例外が発生します。データベースのフィールドのNULLをstring型にはキャストできないため、エラーが発生します。
データベースのNULLフィールドをキャストすると、InvalidCastExceptionの例外が発生します。対処法としてはNULLを判定するか、キャスト部分をtryブロックで囲みcatchで処理する方法があります。tryブロックで囲む場合は、それぞれの代入部をブロックで囲む必要があるため、コードが冗長になります。
キャストする直前でフィールドがNULLか判定する方法を利用します。
コードを下記に変更します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace SQLExecDemo
{
public partial class FormSQLNull : Form
{
public FormSQLNull()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string constr = @"Data Source=192.168.64.98;Initial Catalog=iPentecSandBox;Connect Timeout=60;Persist Security Info=True;User ID=sa;Password=adelieC#8851SQL";
SqlConnection con = new SqlConnection(constr);
con.Open();
try {
string sqlstr = "select * from working";
SqlCommand com = new SqlCommand(sqlstr, con);
SqlDataReader sdr = com.ExecuteReader();
while (sdr.Read() == true) {
string name = (string)sdr["name"];
decimal value = (decimal)sdr["value"];
string category = "";
if (sdr["category"] == DBNull.Value) {
category = "(NULL)";
}
else {
category = (string)sdr["category"];
}
string memo = (string)sdr["memo"];
textBox1.Text += string.Format("{0} / {1:g} / {2} / {3} \r\n",
name.Trim(), value, category.Trim(), memo.Trim());
}
}
finally {
con.Close();
}
}
}
}
NULLの可能性があるフィールドを読み込む部分のコードが下記になります。
SqlDataReaderで列名を添え字にしてアクセスし、フィールドの値を取得しますが、フィールドの値がNULLの場合、値がDBNull.Value
になります。フィールドの値がDBNull.Value
であるか判定し、NULLでない場合のみにキャストする動作にすることで、NULLのキャストによるInvalidCastException例外の発生を防ぐことができます。
string category = "";
if (sdr["category"] == DBNull.Value) {
category = "(NULL)";
}
else {
category = (string)sdr["category"];
}
プロジェクトを実行します。下図のウィンドウが表示されます。
[button1]をクリックします。テーブルのレコード一覧がテキストボックスに表示されます。NULLのキャストで例外は発生せず、NULLのフィールドは"(NULL)"の文字列が表示される動作となっています。