在 SqlDataAdapter.Update() 中获取错误消息

Posted

技术标签:

【中文标题】在 SqlDataAdapter.Update() 中获取错误消息【英文标题】:Getting error message in SqlDataAdapter.Update() 【发布时间】:2016-07-14 19:43:38 【问题描述】:

我有一个数据库表(在本例中为空)

create table words
(
    id int not null,
    word nvarchar(50) not null
)

还有一个DataGridView,我是这样填写的:



    private SqlConnection _conn;
    private SqlDataAdapter _wordsAdapter;
    private DataTable _wordsDataTable = new DataTable();
    private DataGridView _tblWords;

    private void FillWords()
    
        _wordsAdapter = new SqlDataAdapter(new SqlCommand("select id, word from words", _conn));
        _wordsAdapter.Fill(_wordsDataTable);

        DataGridViewColumn column = new DataGridViewTextBoxColumn();
        column.DataPropertyName = "id";
        column.Name = "id";
        _tblWords.Columns.Add(column);

        column = new DataGridViewTextBoxColumn();
        column.DataPropertyName = "word";
        column.Name = "word";
        _tblWords.Columns.Add(column);

        _tblWords.DataSource = _wordsDataTable;
    

    private void Update()
    
        _wordsAdapter.InsertCommand = new SqlCommand("insert into words (id, word) values (@id, @word)", _conn);
        SqlParameter p = _wordsAdapter.InsertCommand.Parameters.Add("@id", SqlDbType.Int);
        p.SourceColumn = "id";
        p.SourceVersion = DataRowVersion.Original;
        p = _wordsAdapter.InsertCommand.Parameters.Add("@word", SqlDbType.NVarChar);
        p.SourceColumn = "word";
        p.SourceVersion = DataRowVersion.Original;
        _wordsAdapter.Update(_wordsDataTable);
    

然后我用一些值填充单行 _tblWords 并调用 Update()。并收到此消息:

抛出异常:“System.Data.SqlClient.SqlException”在 System.Data.dll 附加信息:无法将值 NULL 插入列 'id'、表 'DB.MDF.dbo.words';列不允许空值。插入 失败。

为什么 'id' 的值不是从 DataTable 中获取的?我做错了什么?

更新: 在 Update() 函数的开头插入此代码后,一切正常:



    private void Update()
    
        _wordsDataTable.Rows.Clear();
        _wordsDataTable.Rows.Add(0, "xxx");
        ...

所以只有当我通过 DataGridView 填充 DataTable 时才会出现问题。为什么?!

【问题讨论】:

您正在从 datagridview 获取数据并将其插入到表中。 ID 列应该是主键或标识列,因此它不允许您插入重复值。如果要更新表中的单词列,则使用 UPDATE 语句。 表是空的,所以在这种特殊情况下该行是插入的。没有重复,因为插入的行是表中的第一行。但我仍然得到错误。 我正在尝试运行您的代码。_cb 是什么? 对不起,在这个例子中实际上_cb 不是必需的。将其更改为 'new SqlCommand()' 您是否在调试器中查看过此内容并检查数据表中是否有值? 【参考方案1】:

我猜测问题与 DataGridView 中的最后一个空行有关。

您可以尝试这样的操作,而不是最后一行 _wordsAdapter.Update(_wordsDataTable);

var haveDbNull = _wordsDataTable.Rows.Cast<DataRow>().ToLookup(r => r.ItemArray.Contains(DBNull.Value));

Debug.Print("have DbNull values: " + haveDbNull[true].Count()); // check this number in the Debug Output window
Debug.Print("don't have DbNull values: " + haveDbNull[false].Count()); 

_wordsAdapter.Update(haveDbNull[false].ToArray());  // to update just the rows that dont have DBNull values

【讨论】:

插入的行没有空值。那就是问题所在。当我通过 DataGridView 按值插入它时,出现错误。当我以编程方式将其插入 DataTable 时,一切正常。 我不知道你为什么使用p.SourceVersion = DataRowVersion.Original;。您应该删除它们或将它们更改为 p.SourceVersion = DataRowVersion.Current; msdn.microsoft.com/en-us/library/system.data.datarowversion 我也尝试了 Current,结果相同。如果我完全删除它,还会出现另一个错误,说没有提供参数值。问题是它从 DataTable 中获取 null 值而不是当前值。 那我放弃了.. 你可以试试csharp.net-informations.com/dataadapter/… 的示例,然后从那里开始【参考方案2】:

我找到了一些解决方案。我只是删除添加的行并以编程方式添加相同的值。



    object[] rowValues = dt.Rows[row].ItemArray;
    dt.Rows.RemoveAt(row);
    dt.Rows.Add(rowValues);

有谁知道不那么丑陋的方法吗?

【讨论】:

【参考方案3】:

解决方法一如既往的简单……


    _dtWords.EndInit();

【讨论】:

以上是关于在 SqlDataAdapter.Update() 中获取错误消息的主要内容,如果未能解决你的问题,请参考以下文章

C# SqlDataAdapter.Update()

在 SqlDataAdapter.Update() 中获取错误消息

当 RowState = Modified 时 SQLDataAdapter.Update() 不更新

SqlDataAdapter.Update(数据表)不工作(不更新数据库)

SqlDataAdapter.Update 直到第二次更新才写入表

200万条记录的SqlDataAdapter.Update()速度极慢