今天做程序的时候,因为要用SqlDatasource绑定存储过程来实现添加数据。这个控件用过不下100遍了,今天才发现Image类型字段需要特别处理。

SqlDataSource控件如果是通过向导来做的话,会自动生成如下代码:
  "studentDataSource" runat= "server" ConnectionString= "<%$ ConnectionStrings:StdITBaseOAConnectionString %>"
    SelectCommand= "SELECT Student.* FROM Student" InsertCommand= "spStudentRecordAdd"
                InsertCommandType= "StoredProcedure" >
    
                        "StudentName" Type= "String" />
                        "StudentID" Type= "Int32" />
                        "Photo" Type= "Object" />
                

  
运行时会出现“sql_variant类型不能转换为Image类型的异常”,一看就是类型不匹配的异常,可惜的是Parameter 没有Image类型。这时,请手工去掉这行:
"Photo" Type= "Object" />
在此,这个Type="Object"将会产生一个sql_variant类型的参数。然而,该sql_variants类 型不能用来存储图像或varbinary(MAX)数据类型,因为该sql_variant的内在数据大小不能超过8,000个字节。(如果你试图使用 Type="Object",然后试图保存超过8,000字节大小的二进制数据,那么,系统将抛出一个异常并显示消息"Parameter '@ImageData' exceeds the size limit for the sql_variant datatype";如果你试图添加不到8,000字节大小的二进制数据,那么,该异常将显示消息"Implicit conversion from data type sql_variant to varbinary(max) is not allowed")。

当然,我们肯定不能不管这个字段,下面是我试验成功的一种做法,仅供有同样疑惑的同学参考:
         protected void studentDataSource_Inserting( object sender, SqlDataSourceCommandEventArgs e)
        {
                FileUpload fu = FormView1.FindControl( "FileUpload1") as FileUpload;
                 byte[] p_w_picpathData = new byte[0];
                 if (fu != null && fu.HasFile)
                {
                        p_w_picpathData = fu.FileBytes;
                }
                System.Data.SqlClient.SqlParameter uploadData = new System.Data.SqlClient.SqlParameter( "@Photo", System.Data.SqlDbType.Image);
                uploadData.Value = p_w_picpathData;
                e.Command.Parameters.Add(uploadData);
        }
代码中使用了FormView控件,同学组要根据实际情况来理解。这段代码里最核心的部分是构建一个SqlParameter,对应 Photo,并加到Insert Command中。

另外上面的
studentDataSource_Inserting方法是SqlDataSource控件的Inserting事件的实现。一开始我用FormView的Inserting事件,发现那里面无法得到Command对象,只能对参数的DefaultValue进行赋值。所以才想到了SqlDataSource

问题虽然解决了,但是我还是建议不要将图片保存到数据库字段中。另外,可能还有其它的方法吧,欢迎各位讨论。