使用 SqlParameter 插入可為 NULL 的欄位(DateTime、Int)時,空字串會被轉為預設值(1900-01-01、0),必須顯式指派 DBNull.Value 才能真正寫入 NULL。
// 錯誤:空字串轉換為預設值
cmd.Parameters.Add("@BirthDate", SqlDbType.DateTime).Value = txtDate.Text; // "" -> 1900-01-01
cmd.Parameters.Add("@Score", SqlDbType.Int).Value = txtScore.Text; // "" -> 0
// 錯誤:直接指派空字串給強型別參數會拋出例外
cmd.Parameters.Add(new SqlParameter("@BirthDate", SqlDbType.DateTime));
cmd.Parameters["@BirthDate"].Value = txtDate.Text; // FormatException
cmd.Parameters.Add(new SqlParameter("@BirthDate", SqlDbType.DateTime));
if (!string.IsNullOrEmpty(txtDate.Text))
{
cmd.Parameters["@BirthDate"].Value = DateTime.Parse(txtDate.Text);
}
else
{
cmd.Parameters["@BirthDate"].Value = DBNull.Value; // 關鍵:明確指定 NULL
}
// 簡寫擴充方法
public static void SetValueOrNull(this SqlParameter param, string input, Func converter)
{
param.Value = string.IsNullOrEmpty(input) ? DBNull.Value : converter(input);
}
// 使用
cmd.Parameters["@BirthDate"].SetValueOrNull(txtDate.Text, DateTime.Parse);
cmd.Parameters["@Score"].SetValueOrNull(txtScore.Text, int.Parse);
null 在參數指派時可能被忽略或轉為預設值,必須用 System.DBNull.ValueDateTime.Parse("") 拋出 FormatException// EF Core:屬性型別用 DateTime?、int?,直接指派 null
entity.BirthDate = string.IsNullOrEmpty(txtDate.Text) ? (DateTime?)null : DateTime.Parse(txtDate.Text);
// Dapper:匿名物件屬性指派 null
conn.Execute("INSERT INTO T (BirthDate, Score) VALUES (@BirthDate, @Score)",
new { BirthDate = string.IsNullOrEmpty(txtDate.Text) ? (DateTime?)null : DateTime.Parse(txtDate.Text),
Score = string.IsNullOrEmpty(txtScore.Text) ? (int?)null : int.Parse(txtScore.Text) });