我有一个简单的员工数据库,它允许我添加一个新员工,我的一些文本框字段留空(我正在使用winform)。它目前在数据库中正常工作。它注册NULL值代替空文本框。我现在的问题是如何在gridview中显示数据库中的所有员工: 当我运行该程序时,它弹出一个消息框,说“对象无法从DBNull转换为其他类型”。是因为我的数据库中的'age'和'married'列包含一些空值?请帮助,我正在尝试了解如何在c#中使用可空类型与mssql数据库。
public static List<Employee> GetEmployees()
{
List<Employee> empListToReturn = new List<Employee>();
SqlConnection conn = GetConnection();
string queryStatment = "SELECT * FROM Employee";
SqlCommand sqlCmd = new SqlCommand(queryStatment, conn);
try
{
conn.Open();
SqlDataReader reader = sqlCmd.ExecuteReader();
while (reader.Read())
{
Employee emp = new Employee();
emp.FirstName = reader["firstname"].ToString();
emp.LastName = reader["lastname"].ToString();
emp.Age = Convert.ToInt32(reader["age"]);
emp.Married = (reader["married"]);
empListToReturn.Add(emp);
}
reader.Close();
}
catch (SqlException ex)
{
throw ex;
}
finally
{
conn.Close();
}
return empListToReturn;
}
答案 0 :(得分:1)
如错误所述,您无法将null
转换为其他类型。特别是在这种情况下int
:
emp.Age = Convert.ToInt32(reader["age"]);
(因为价值类型不能是null
。)
转换前只需检查null
:
if (reader["age"] == DBNull.Value)
emp.Age = 0;
else
emp.Age = Convert.ToInt32(reader["age"]);
编辑:正如评论中所指出的,有多种方法可以做到这一点。有些可能比其他人更有效。例如:
if (reader.IsDBNull(reader.GetOrdinal("age")))
emp.Age = 0;
else
emp.Age = reader.GetInt32(reader.GetOrdinal("age")));
除非性能差异很大,否则在使用命名列而不是序号时我可能更喜欢前者,因为这需要额外的方法调用来获取序数。 (除非我在MSDN上看不到字符串重载?)
此外,如果您不希望0
作为选项,则可以将.Age
属性从int
更改为Nullable<int>
(或int?
简而言之。这将允许您在该对象上设置null
值:
if (reader.IsDBNull(reader.GetOrdinal("age")))
emp.Age = null; // <-- here
else
emp.Age = reader.GetInt32(reader.GetOrdinal("age")));
当0
(有效值)和null
(缺少值)之间存在明显的语义差异时,这通常非常有用。
还值得注意的是,这段代码是不好的做法:
catch (SqlException ex)
{
throw ex;
}
您的catch
块不仅没有实际处理异常,而且实际上覆盖堆栈跟踪。这将使调试更加困难。由于catch
块无法执行任何操作,因此请完全删除它。您不需要catch
中的try/finally
。