【问题标题】:How to fix exception:Unable to cast object of type 'System.DBNull' to type 'System.Byte[]'如何修复异常:无法将“System.DBNull”类型的对象转换为“System.Byte []”类型
【发布时间】:2019-10-17 17:37:06
【问题描述】:

我有一个名为 tblStaff 的表,其中名为 staffImage 的列具有允许存储 Null 的 Image 数据类型。如果用户提供他的照片,那么此列会将图像存储为二进制数据,如果他不提供他的图像,那么它将存储 Null 值。如果此列为 null 值,则 Resource 文件夹中的图像应显示在 pictureBox1 中,如果此列具有二进制数据,则此列中存储为二进制数据的图像应显示在 pictureBox1 中。

CREATE TABLE tblStaff
(
    staffId int not null identity Primary Key,
    staffName varchar(50) not null,
    staffUserName varchar(25) not null,
    staffPassword varchar(30) not null,
    staffPhone varchar(15) not null,
    staffRole int not null,
    staffStatus tinyint not null,
    **staffImage image**
)

    ALTER PROC [dbo].[sp_GetStaffImage]
    @staffId varchar(150)
    as
    SELECT Stf.staffImage as 'Image' FROM tblStaff Stf WHERE 
    staffID=@staffId


.
.
.
.

string staffID = Convert.ToString(dataGridViewStaff.Rows[e.RowIndex].Cells["Staff Id"].Value);
..............
.............
..........
...........

SqlConnection con1 = new SqlConnection(cs);
con.Open();
SqlCommand cmd1 = new SqlCommand("sp_GetStaffImage", con);
cmd1.CommandType = CommandType.StoredProcedure;
cmd1.Parameters.AddWithValue("@staffId", staffID);
SqlDataAdapter sda1 = new SqlDataAdapter(cmd1);
DataSet ds = new DataSet();
sda1.Fill(ds);

if(ds.Tables[0].Rows.Count>0)
{
   var img = (byte[])ds.Tables[0].Rows[0][0];

   if (img != Null) //code if the data in column named staffImage is 
                    Binary data then show the image                        
                    in PictureBox1 from the database.
   {

         MemoryStream ms = new MemoryStream(img);
         pictureBox1.Image = new Bitmap(ms);
   }
   else  //code if the data in column named staffImage is Null then show the image in PictureBox1 
           from Resource folder .
   {
       pictureBox1.ImageLocation = "Resources/human.png";
   }

}
con.Close();

通过运行上面的代码,我得到了如下异常: 无法将“System.DBNull”类型的对象转换为“System.Byte[]”类型。

【问题讨论】:

    标签: c# sql .net windows ado.net


    【解决方案1】:

    无法将“System.DBNull”类型的对象转换为“System.Byte[]”类型

    您的异常源于以下调用:

     var img = (byte[])ds.Tables[0].Rows[0][0];
    

    这是从这里发生的:

     ds.Tables[0].Rows[0][0] // This is DBNull, you can't cast it to byte[]
    

    您正在尝试将System.DBNull 转换为System.Byte[],这不起作用。您需要先检查此值,请参见下文。

    注意:还有 一种方法可以检查这一点

     var img = ds.Tables[0].Rows[0][0] == DbNull.Value ? null : (byte[])ds.Tables[0].Rows[0][0];
    

    @madreflection 建议的替代方法:

     var img = ds.Tables[0].Rows[0].Field<byte[]>(0);
    

    【讨论】:

    • 没有必要提供一个有竞争力的答案,因为这已经很好了,所以我会提供这个:var img = ds.Tables[0].Rows[0].Field&lt;byte[]&gt;(0); Field&lt;T&gt; 扩展方法会为您检查(实现实际上非常迷人)。
    【解决方案2】:

    “无法将 'System.DBNull' 类型的对象转换为 xxx 类型”的例外是正确的,也非常简单,因为您尝试从 DataRow 转换的列值是 DbNull。

    如果您从 DataTable 中读取行,如果该列被键入为可空列,则应始终检查 DbNull。

    例如,代码应该是这样的:

     var img = (byte[])(ds.Tables[0].Rows[0][0] == DbNull.Value ? null : ds.Tables[0].Rows[0][0]);
    
    

    【讨论】:

      【解决方案3】:

      作为替代答案,并且由于 SQL Server 中的 IMAGE 列类型已被弃用,您可以使用 VARBINARY(MAX) NOT NULL 作为列类型并将默认值设置为 0x。

      这样,您将始终从查询中至少返回 byte[0],而不必担心 DBNull 检查。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-30
        • 1970-01-01
        • 1970-01-01
        • 2015-03-13
        相关资源
        最近更新 更多