2010-05-14 52 views
0

我可以得到这个工作,但我觉得好像我没有做得很好。CommandBuilder和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,或在封装变化的试验和错误的工作开始/ 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解决方案;虽然,我觉得它不是解决方案。

希望这可以帮助别人。