CommandBuilder 和 SqlTransaction 插入/更新行

Posted

技术标签:

【中文标题】CommandBuilder 和 SqlTransaction 插入/更新行【英文标题】:CommandBuilder and SqlTransaction to insert/update a row 【发布时间】:2010-05-14 21:52:14 【问题描述】:

我可以让它工作,但我觉得我做得不好。

第一次运行时,它按预期工作,并在“thisField”包含“doesntExist”的位置插入新行

但是,如果我随后运行它,我会收到一个运行时错误,我无法插入重复键,因为它违反了主键“thisField”。


static void Main(string[] args)
           
    using(var sqlConn = new SqlConnection(connString) )
    
        sqlConn.Open();
        var dt = new DataTable();

        var sqlda = new SqlDataAdapter("SELECT * FROM table WHERE thisField ='doesntExist'", sqlConn);
        sqlda.Fill(dt);

        DataRow dr = dt.NewRow();

        dr["thisField"] = "doesntExist"; //Primary key

        dt.Rows.Add(dr);

        //dt.AcceptChanges(); //I thought this may fix the problem. It didn't.

        var sqlTrans = sqlConn.BeginTransaction();

        try
        
            sqlda.SelectCommand = new SqlCommand("SELECT * FROM table WITH (HOLDLOCK, ROWLOCK) WHERE thisField = 'doesntExist'", sqlConn, sqlTrans);

            SqlCommandBuilder sqlCb = new SqlCommandBuilder(sqlda);

            sqlda.InsertCommand = sqlCb.GetInsertCommand();
            sqlda.InsertCommand.Transaction = sqlTrans;

            sqlda.DeleteCommand = sqlCb.GetDeleteCommand();
            sqlda.DeleteCommand.Transaction = sqlTrans;

            sqlda.UpdateCommand = sqlCb.GetUpdateCommand();
            sqlda.UpdateCommand.Transaction = sqlTrans;

            sqlda.Update(dt);

            sqlTrans.Commit();
        
        catch (Exception)
        
            //...
        
    

即使我可以通过移动 AcceptChanges 的反复试验或在 Begin/EndEdit 中封装更改来实现这一点,然后我开始遇到“并发冲突”,它不会更新更改,而是告诉我无法更新 1 个受影响行中的 0 个。

我错过了什么疯狂的明显东西吗?

【问题讨论】:

【参考方案1】:

我能够通过在填充数据表后手动删除行来解决我的问题。我无法使用dt.Clear(),因为尝试插入具有重复主键的记录仍然会导致异常。


sqladapter.Fill(dt);

foreach( DataRow d in dt.Rows )
    d.Delete();

DataRow dr = dt.NewRow();

dr.BeginEdit();
//update dr
dr.EndEdit();

dt.Rows.Add(dr);

上面将成功地让我插入一个新行,并更新一个预先存在的行。删除 foreach 会生成“无法在对象中插入重复键”,所以我觉得我至少找到了 a 解决方案;虽然,我觉得这不是 解决方案。

希望这对某人有所帮助。

【讨论】:

以上是关于CommandBuilder 和 SqlTransaction 插入/更新行的主要内容,如果未能解决你的问题,请参考以下文章

C#.NET sqlDatabase CommandBuilder 和 DataAdapter:名称“适配器”在当前上下文中不存在

C#使用DataSet Datatable更新数据库的三种实现方法

运行弹簧批处理作业的多个实例时出现死锁

sqlCommandBuilder 更新未按预期工作

C#基础之使用DataSet与Datatable更新数据库的三种实现方法

为啥我的 sql 命令不接受表名的带引号标识符?