【问题标题】:Exception about data type数据类型异常
【发布时间】:2017-07-26 20:22:14
【问题描述】:

我创建了一个应用程序,其中有一个 datagridview。当我单击一个按钮时,写入 datagridview 的数据会以表格的形式发送到我的数据库。但我有一个例外,我迷路了。

错误:System.Data.SqlClient.SqlException: 'Fail to convert nvarchar value 'B003382A3' to int value。'

我什至不知道他为什么尝试转换为 int,因为我的数据在我的数据库中是 nvarchar。我唯一的建议是他正在反转单元格。

我的代码:

private void metroButton1_Click(object sender, EventArgs e)
{
    SqlConnection maConnexion = new SqlConnection("Server= localhost; Database= Seica_Takaya;Integrated Security = SSPI; ");
    maConnexion.Open();

    foreach (DataGridViewRow row in dataGridView1.Rows)
    {
        if ((row.Cells[20].Value != null) && (bool)row.Cells[20].Value)
        {
            SqlCommand command = maConnexion.CreateCommand();

            command = new SqlCommand("update FailAndPass set Machine=@machine, ProgCode=@pc, BoardName=@BName, BoardNumber=@BNumber, Tester=@T, DateTest=@DT, TimeTest=@TT, TimeStart=@TS, FComponent=@FC, Message=@Mess, TotalTestProg=@TTP, ReadValue=@RV, ValueReference=@VR, PTolerance=@PT, FaultCodeByOP=@FCBO, FaultDetail=@FD,  RepairingDate=@RD, RepairingTime = @RT, ReportingOperator=@RO WHERE SerialNum=@Serial", maConnexion);
            command.Parameters.AddWithValue("@Serial", textBox1.Text);
            command.Parameters.AddWithValue("@Machine", row.Cells[0].Value != null ? row.Cells[0].Value : DBNull.Value);
            command.Parameters.AddWithValue("@pc", row.Cells[2].Value != null ? row.Cells[2].Value : DBNull.Value);
            command.Parameters.AddWithValue("@BName", row.Cells[3].Value != null ? row.Cells[3].Value : DBNull.Value);
            command.Parameters.AddWithValue("@BNumber", row.Cells[4].Value != null ? row.Cells[4].Value : DBNull.Value);
            command.Parameters.AddWithValue("@T", row.Cells[5].Value != null ? row.Cells[5].Value : DBNull.Value);
            command.Parameters.AddWithValue("@DT", row.Cells[6].Value != null ? row.Cells[6].Value : DBNull.Value);
            command.Parameters.AddWithValue("@TT", row.Cells[7].Value != null ? row.Cells[7].Value : DBNull.Value);
            command.Parameters.AddWithValue("@TS", row.Cells[8].Value != null ? row.Cells[8].Value : DBNull.Value);
            command.Parameters.AddWithValue("@FC", row.Cells[9].Value != null ? row.Cells[9].Value : DBNull.Value);
            command.Parameters.AddWithValue("@Mess", row.Cells[10].Value != null ? row.Cells[10].Value : DBNull.Value);
            command.Parameters.AddWithValue("@TTP", row.Cells[11].Value != null ? row.Cells[11].Value : DBNull.Value);
            command.Parameters.AddWithValue("@RV", row.Cells[12].Value != null ? row.Cells[12].Value : DBNull.Value);
            command.Parameters.AddWithValue("@VR", row.Cells[13].Value != null ? row.Cells[13].Value : DBNull.Value);
            command.Parameters.AddWithValue("@PT", row.Cells[14].Value != null ? row.Cells[14].Value : DBNull.Value);
            command.Parameters.AddWithValue("@FCBO", row.Cells[15].Value != null ? row.Cells[15].Value : DBNull.Value);
            command.Parameters.AddWithValue("@FD", row.Cells[16].Value != null ? row.Cells[16].Value : DBNull.Value);
            command.Parameters.AddWithValue("@RD", row.Cells[17].Value != null ? row.Cells[17].Value : DBNull.Value);
            command.Parameters.AddWithValue("@RT", row.Cells[18].Value != null ? row.Cells[18].Value : DBNull.Value);
            command.Parameters.AddWithValue("@RO", row.Cells[19].Value != null ? row.Cells[19].Value : DBNull.Value);
            command.ExecuteNonQuery();

        }
    }

    maConnexion.Close();
    this.Hide();
    Repair rep = new Repair();
    rep.Show();
}

这是我的数据库的图片:


我使用了调试器,但似乎我的单元格不正确。我的datagridview的第一列是Machine,代码中对应的单元格是row.cells1

似乎我所有的单元格的顺序都不正确。这到底是什么?我的意思是,通常 BoardName 是第三个单元格,但我把 row.cell[2] 我没有错误了。而且它不是唯一一个出现此错误的单元格。

【问题讨论】:

  • FailAndPass中的所有列的类型都是NVARCHAR?
  • 我假设除SerialNum 之外的所有列都是可为空的。尝试使用DbType 指定字符串参数的数据类型,例如command.Parameters.AddWithValue("@Machine", row.Cells[0].Value != null ? row.Cells[0].Value : DBNull.Value).DbType = DbType.String;.
  • 旁注:private void AddParameter(SqlCommand command, string ParameterName, object value) { command.Parameters.AddWithValue(ParameterName, value != null ? value : DBNull.Value); }
  • blogs.msmvps.com/jcoehoorn/blog/2014/05/12/… - 引自博客文章“AddWithValue() 函数存在问题:它必须为您的查询参数推断数据库类型。事情是这样的:有时它会出错。 "
  • 不是一个整数!!!

标签: c# sql sql-server visual-studio datagridview


【解决方案1】:

更新您的更新:

您选择的单元格在数据库中有一个对应的int 值。我建议你检查你的datagridview 人口 - 至于行内的位置要改变,代码肯定有变化。

为了将来参考,最好不要否认数据库表中有一个 int,如果有的话,因为它确实有助于回答问题,并且可以提供更简单的解决方案并指导您查看的位置。

剩下的答案 - 虽然有帮助 - 在这个阶段是装点门面的。


使用

row.Cells[0].Value.ToString() // wherever you are getting the value and it's not null.

也可以使用

command.Parameters.Add(.../...

example

parameter = command.Parameters.Add("@InputParm", OleDbType.VarChar, 12);  
// which explicitly types the datatype - with the number of char.
parameter.Value = "Sample Value";  

can be issues 使用 AddWithValue 进行数据类型转换。

【讨论】:

  • 我已经测试了你的代码,但仍然没有同样的错误。不要认为它会来自添加。
【解决方案2】:

我总是使用这种风格的代码来处理 SQL

 SqlConnection connection = new 
 SqlConnection(ConfigurationManager.AppSettings["SQLConnectionString"]);

 SqlCommand command = new SqlCommand();
 command.CommandTimeout = 1000;
 command.Connection = connection;
 command.CommandType = CommandType.StoredProcedure;
 command.CommandText = "KULLANICI_OKU";

 SqlParameter parameter = new SqlParameter();
 parameter.Direction = ParameterDirection.Input;
 parameter.ParameterName = "@KULLANICI";
 parameter.DbType = DbType.String;
 parameter.Value = user;
 command.Parameters.Add(parameter);

在我看来,使用存储过程是 sql 的更好方法。

【讨论】:

    【解决方案3】:

    您应该知道的第一件事:您不能将DBNull.Value 分配给string(SQL 中的nvarchar)或其他结构值类型,因为它们彼此不兼容。在DBNull.Valuestring(或结构类型)之间使用三元运算符的常用方法是将DBNull.Value 转换为object 类型。

    下面是一个如何在三元运算符中对DBNull.Value 执行强制转换的示例:

    // a & b are cell numbers for respective cells
    // change to any number representing the cell order
    
    foreach (DataGridViewRow row in dataGridView1.Rows)
    {
        if ((row.Cells[20].Value != null) && (bool)row.Cells[20].Value)
        {
            SqlCommand command = maConnexion.CreateCommand();
    
            command = new SqlCommand("update FailAndPass set Machine=@machine, ProgCode=@pc, BoardName=@BName, BoardNumber=@BNumber, Tester=@T, DateTest=@DT, TimeTest=@TT, TimeStart=@TS, FComponent=@FC, Message=@Mess, TotalTestProg=@TTP, ReadValue=@RV, ValueReference=@VR, PTolerance=@PT, FaultCodeByOP=@FCBO, FaultDetail=@FD,  RepairingDate=@RD, RepairingTime = @RT, ReportingOperator=@RO WHERE SerialNum=@Serial", maConnexion);
            // other parameters
    
            // integer value parameter example
            command.Parameters.Add("@pc", SqlDbType.Int).Value = row.Cells[a].Value != null ? row.Cells[a]Value : (object)DBNull.Value;
    
            // string value parameter example
            command.Parameters.Add("@BName", SqlDbType.NVarChar).Value = (row.Cells[b].Value != null ? (object)row.Cells[b].Value : (object)DBNull.Value).ToString();
    
            // other parameters
    
            command.ExecuteNonQuery();
    
        }
    }
    
    // other stuff
    

    如果编译器支持空合并操作符,那就更简单了:

    // integer parameter
    command.Parameters.Add("@pc", SqlDbType.Int).Value = row.Cells[a].Value ?? (object)DBNull.Value;
    
    // string parameter
    command.Parameters.Add("@BName", SqlDbType.NVarChar).Value = (row.Cells[b].Value ?? (object)DBNull.Value).ToString();
    

    参考:

    How do I Parameterize a null string with DBNull.Value clearly and quickly

    【讨论】:

    • 当我使用这种方式时,我有这个错误:System.FormatException:在 int32 中转换值字符串失败。'
    【解决方案4】:

    好的,我找到了解决问题的方法。

    代码如下:

    private void metroButton1_Click(object sender, EventArgs e)
        {
            SqlConnection maConnexion = new SqlConnection("Server= localhost; Database= Seica_Takaya;Integrated Security = SSPI; ");
            maConnexion.Open();
    
            foreach (DataGridViewRow row in dataGridView1.Rows)
            {
    
    
                if ((row.Cells[20].Value != null) && (bool)row.Cells[20].Value)
                {
    
                    SqlCommand command = maConnexion.CreateCommand();
    
    
                    command = new SqlCommand("update FailAndPass set Machine=@machine, ProgCode=@pc, BoardName=@BName, BoardNumber=@BNumber, Tester=@T, DateTest=@DT, TimeTest=@TT, TimeStart=@TS, FComponent=@FC, Message=@Mess, TotalTestProg=@TTP, ReadValue=@RV, ValueReference=@VR, PTolerance=@PT, FaultDetail=@FD, RepairingDate=@RD, RepairingTime=@RT, ReportingOperator=@RO, FaultCodeByOP=@FCBO  WHERE SerialNum=@Serial", maConnexion);
    
                    command.Parameters.AddWithValue("@Machine", row.Cells[1].Value != null ? row.Cells[1].Value : DBNull.Value);
                    command.Parameters.AddWithValue("@Serial", textBox1.Text);
                    command.Parameters.AddWithValue("@pc", row.Cells[3].Value != null ? row.Cells[3].Value : DBNull.Value);
                    command.Parameters.AddWithValue("@BName", row.Cells[4].Value != null ? row.Cells[4].Value : DBNull.Value);
                    command.Parameters.AddWithValue("@BNumber", row.Cells[5].Value != null ? row.Cells[5].Value : DBNull.Value);
                    command.Parameters.AddWithValue("@T", row.Cells[6].Value != null ? row.Cells[6].Value : DBNull.Value);
                    command.Parameters.AddWithValue("@DT", row.Cells[7].Value != null ? row.Cells[7].Value : DBNull.Value);
                    command.Parameters.AddWithValue("@TT", row.Cells[8].Value != null ? row.Cells[8].Value : DBNull.Value);
                    command.Parameters.AddWithValue("@TS", row.Cells[9].Value != null ? row.Cells[9].Value : DBNull.Value);
                    command.Parameters.AddWithValue("@FC", row.Cells[11].Value != null ? row.Cells[11].Value : DBNull.Value);
                    command.Parameters.AddWithValue("@Mess", row.Cells[10].Value != null ? row.Cells[10].Value : DBNull.Value);                   
                    command.Parameters.AddWithValue("@TTP", row.Cells[12].Value != null ? row.Cells[12].Value : DBNull.Value);
                    command.Parameters.AddWithValue("@RV", row.Cells[13].Value != null ? row.Cells[13].Value : DBNull.Value);
                    command.Parameters.AddWithValue("@VR", row.Cells[14].Value != null ? row.Cells[14].Value : DBNull.Value);
                    command.Parameters.AddWithValue("@PT", row.Cells[15].Value != null ? row.Cells[15].Value : DBNull.Value);
                    command.Parameters.AddWithValue("@FD", row.Cells[16].Value != null ? row.Cells[16].Value : DBNull.Value);
                    command.Parameters.AddWithValue("@RD", row.Cells[17].Value != null ? row.Cells[17].Value : DBNull.Value);
                    command.Parameters.AddWithValue("@RT", row.Cells[18].Value != null ? row.Cells[18].Value : DBNull.Value);
                    command.Parameters.AddWithValue("@RO", row.Cells[19].Value != null ? row.Cells[19].Value : DBNull.Value);
                    command.Parameters.AddWithValue("@FCBO", row.Cells[20].Value != null ? row.Cells[20].Value : DBNull.Value);
    
                    command.ExecuteNonQuery();
    
    
    
    
                }
            }
    

    }

    现在我可以用 add 替换所有 addwithvalue。

    解释:似乎单元格没有像使用列或索引那样被计算在内。我认为该单元正在等待索引 [0] -> [max]。 或者,我看到 row.cells[0] 不包含机器的名称,但为 NULL。 结果,如果我的单元格从索引 [0] 开始,我的所有数据都会偏移。然后,果然,BoardName在ProgCode Cell中,所以插入到数据库中的ProgCode列中,它是int型的,所以引发了错误!

    这太令人兴奋了,我已经一步一步地做到了。但是感谢大家的帮助,因为至少你已经让我学到了一些东西!

    【讨论】:

    • 据我记忆,Cell[0] 是行选择器。
    • 哦,这解释了很多
    猜你喜欢
    • 1970-01-01
    • 2018-09-24
    • 2016-04-11
    • 2023-03-09
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多