使用 C# 和 SQL 将文本和图像添加到数据库

Posted

技术标签:

【中文标题】使用 C# 和 SQL 将文本和图像添加到数据库【英文标题】:Adding text and image to database with C# and SQL 【发布时间】:2021-04-29 19:21:33 【问题描述】:

以下 Windows 窗体应用程序接受姓名、年龄、性别、描述和图像的输入。

但是当点击“保存信息”按钮时出现以下异常错误:

System.Data.SqlClient.SqlException: " Operand type ***: nvarchar is incompatible with image"

不太清楚为什么脚本将图像解释为 nvarchar 数据类型。

这是函数的存储过程。

ALTER PROCEDURE [dbo].[usp_Students_InsertNewStudent]
(
    @StudentName NVARCHAR(200)
    ,@Age NVARCHAR(50)
    ,@Gender NVARCHAR(50)
    ,@Description NVARCHAR(MAX)
    ,@Image IMAGE
    ,@CreatedBy NVARCHAR(50)
)
AS
    BEGIN
        INSERT INTO [dbo].[Students]
           ([StudentName]
           ,[Age]
           ,[Gender]
           ,[Description]
           ,[Image]
           ,[CreatedBy]
           ,[CreatedDate])
     VALUES
        (
            @StudentName
            ,@Age
            ,@Gender
            ,@Description
            ,@Image
            ,@CreatedBy
            ,GETDATE()
        )

    END

以及相关代码。


        private void SaveButton_Click(object sender, EventArgs e)
        
            if(IsFormValid())
            
                //Do Update Process
                using (SqlConnection con = new SqlConnection(AppConnection.GetConnectionString())) 
                
                    using (SqlCommand cmd = new SqlCommand("usp_Students_InsertNewStudent", con))
                    
                        cmd.CommandType = CommandType.StoredProcedure;

                        cmd.Parameters.AddWithValue("@StudentName", StudentNameTextBox.Text.Trim());
                        cmd.Parameters.AddWithValue("@Age", AgeTextBox.Text.Trim());
                        cmd.Parameters.AddWithValue("@Gender", GenderTextBox.Text.Trim());
                        cmd.Parameters.AddWithValue("@Description", DescriptionTextBox.Text.Trim());
                        cmd.Parameters.AddWithValue("@Image", IdPictureBox.ImageLocation);
                        cmd.Parameters.AddWithValue("@CreatedBy", LoggedInUser.UserName);


                        if (con.State != ConnectionState.Open)
                            con.Open();

                        cmd.ExecuteNonQuery();

                        MessageBox.Show("Student is successfully updated in the database.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        ResetFormControl();
                    
                
            

        private bool IsFormValid()
        
            if (StudentNameTextBox.Text.Trim() == string.Empty)
            
                MessageBox.Show("Student name is Required.", "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                StudentNameTextBox.Focus();
                return false;
            

            if (StudentNameTextBox.Text.Length >= 200)
            
                MessageBox.Show("Student Name length should be less than or equal to 200 characters.", "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                StudentNameTextBox.Focus();
                return false;
            
            return true;
        

        private void UploadButton_Click(object sender, EventArgs e)
        
            String ImageLocation = "";
            try
            
                OpenFileDialog dialog = new OpenFileDialog();
                dialog.Filter = "Image Files(*.jpeg;*.bmp;*.png;*.jpg)|*.jpeg;*.bmp;*.png;*.jpg";

                if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                
                   ImageLocation = dialog.FileName;
                   IdPictureBox.ImageLocation = ImageLocation;
                
            
            catch (Exception)
            
                MessageBox.Show("An Error Occured", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            
        

【问题讨论】:

不要使用AddWithValue(这里有很多关于为什么不使用的信息)。相反,使用正确的类型定义参数,然后分配一个值。看看能不能解决。如果有帮助,我可以发布确切的代码作为答案。具体来说,cmd.Parameters.AddWithValue("@Image", IdPictureBox.ImageLocation); 这一行是你的问题。 确定确切的代码是什么? 已经问过了...使用字节数组而不是路径 这能回答你的问题吗? C# Data Connections Best Practice? 【参考方案1】:

你的问题是这一行:

cmd.Parameters.AddWithValue("@Image", IdPictureBox.ImageLocation);

这是图像所在位置的字符串。正在从 C# 字符串转换为 SQL nvarchar。

您想插入实际图像。我怀疑这可能单独起作用:

cmd.Parameters.AddWithValue("@Image", IdPictureBox.Image);

但我总是尽量避免使用AddWithValue,因为它会推断类型。

这是另一种方式:

cmd.Parameters.Add("@Image", SqlDbType.Image).Value = IdPictureBox.Image;

注意这明确定义了 SQL 类型,AddWithValue 推断它。

为此,请确保您指定与架构匹配的 SqlDbType

下面是如何做同样的事情,例如,使用字节数组:

var image = IdPictureBox.Image;
using (var ms = new MemoryStream())

    image.Save(ms, image.RawFormat);
    cmd.Parameters.Add("@Image", SqlDbType.VarBinary).Value = ms.ToArray();

在任何一种情况下,使用此方法的数据类型都是显式的。

【讨论】:

【参考方案2】:

数据库中的类型是IMAGE,是二进制数据类型。但是随后您尝试将 path 保存到该字段中的图像文件中。图片文件的路径是文本(VARCHAR)。

你想把图片保存在数据库中,还是引用图片的路径?如果是前者,数据库字段会更好VARBINARY,然后你实际上必须将图像的字节数组保存到字段中,而不是图像的路径。

如果是后者,则字段类型应为VARCHAR,然后您可以照常进行。

【讨论】:

以上是关于使用 C# 和 SQL 将文本和图像添加到数据库的主要内容,如果未能解决你的问题,请参考以下文章

WPF C# 在运行时将文本和图像添加到 ComboBox

如何使用 C# 和 SQL 将存储在数据库中的图像加载到图片框对象中

使用 xslt 模板将多个图像添加到 docx 文件

如何使用 web api 将图像和文本从 android 应用程序发送到 sql server

动态数据显示 - WPF - 需要将文本添加到画布 - C#

WPF C#将结果缓存到文本然后到列表框