CommandBuilder和SqlTransaction插入/更新一行

时间:2010-05-14 21:52:14

标签: sqlconnection sqlcommandbuilder sqltransaction

我可以让这个工作,但我觉得我没有正确地做到这一点。

第一次运行时,它按预期工作,并插入一个新行,其中“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 个答案:

答案 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将生成“无法在对象中插入重复键”,因此我觉得我至少找到了 解决方案;虽然,我觉得好像它不是 解决方案。

希望这有助于某人。