采用下面的方法,如果DataSet全是新增的数据就OK,但如果DataSet相应数据库而言,有新增的记录,也有修改的记录时,执行下面的方法只会将DataSet里的数据又全部写回到数据库,修改的记录就重复了。该怎么处理?如何加上事务处理机制?
public int UpdateByDataSetASB(DataSet ds, string sqlStr,string strTblName, string strConnection)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(strConnection))
                {                    SqlDataAdapter myAdapter = new SqlDataAdapter();
                    SqlCommand myCommand = new SqlCommand(sqlStr, conn);
                    myAdapter.SelectCommand = myCommand;
                    SqlCommandBuilder myCommandBuilder = new SqlCommandBuilder(myAdapter);
                    myAdapter.Update(ds, strTblName);                    return 0;
                }
            }
            catch(Exception)
            {
                return -1;
            }
        }

解决方案 »

  1.   

    你可以先将那些修改过的数据,在数据库中删除掉,再将DataSet数据保存进数据库,中间通过事务控制就可以了
      

  2.   

    这个方法我想到过的,不是说SqlCommandBuilder类可以自动识别是新增、修改还是删除吗?
      

  3.   

    你的表有没有设置主键,用SqlCommandBuilder时,表是必须要有主键的
      

  4.   

    有3列主键值,感觉是myAdapter.Update(ds, strTblName);
    这句没有识别到更改的内容,所以就都是插入数据,没有更新动作。不知道修改前的数据是不是:SqlCommand myCommand = new SqlCommand(sqlStr, conn);
    看我理解错没有?
      

  5.   

    rowData[ "ID "]=  Id; 
    dt.Rows.Add(rowData); SqlCommandBuilder   cmd   =   new   SqlCommandBuilder(dprData);//确保对应数据库的表有主键 
    dprData.Update(dt,   "条件 "); 
    dt.AcceptChanges(); 
      

  6.   

    我的sqlStr=Select * from table,是不是这样写只能插入数据,不能更新与删除?
    数据库的主键肯定有,而且是三个字段。我解释一下我的代码,估计是我理解有误,希望大家不笑话我,请大家指正一下:///ds,是我在dataGridView中编辑过后,需要回写数据库的数据,且列名与顺序都与数据库保持一致,但是
    ///这里的数据相对数据库:有新增的,有修改的,有删除了的数据。总之是需要回写数据库的数据
    ///sqlStr=Select * from table,是回写数据库识别的现在数据。
    ///strTblName,就是数据库需要回写的表名。
    ///strConnection,是连接数据库的字符串。
    public int UpdateByDataSetASB(DataSet ds, string sqlStr,string strTblName, string strConnection)
      {
      try
      {
      using (SqlConnection conn = new SqlConnection(strConnection))//实例化一个连接
      {  SqlDataAdapter myAdapter = new SqlDataAdapter();//实例化一SqlDataAdapter类   
      SqlCommand myCommand = new SqlCommand(sqlStr, conn);//连接数据库,返回现在数据
      myAdapter.SelectCommand = myCommand;//载入数据库中的现在数据
      SqlCommandBuilder myCommandBuilder = new SqlCommandBuilder(myAdapter);
      //载入到SqlCommandBuilder实例中
      myAdapter.Update(ds, strTblName);//将需要回写的数据填充进来,自动识别插入、修改、删除动作  return 0;
      }
      }
      catch(Exception)
      {
      return -1;
      }
      }
      

  7.   

    你的DataSet中的修改的数据部分是如何操作的?如果是新增的行,但是已经存在于数据库中,这不叫修改,仍旧是新增,只有在DataSet中加载了数据库中所有数据后,有过改动的数据行才是修改。那个修改的状态不是通过SqlCommandBuilder来自动识别的,那个只负责创建更新语句,修改状态看DataSet中每个数据行的Rowstatus
      

  8.   


    主键怎么能是 三 个字段?一个表中只能有一个column设为主键吧
      

  9.   

    修改状态看DataSet中每个数据行的Rowstatus是怎么体现的?能否读取或修改?
      

  10.   

    谁说的只能一个column做主键? 
      

  11.   

    你说下怎么把多个column都设为主键,我还真不会
      

  12.   

    当然可以读取或修改:
    获取第一行记录的RowState用DataSet.Tables[0].Rows[0].RowState
    设置第一行记录的RowState为新增行用DataSet.Tables[0].Rows[0].SetAdded();
    设置第一行记录的RowState为修改行用DataSet.Tables[0].Rows[0].SetModified();
    设置第一行记录的RowState为删除行用DataSet.Tables[0].Rows[0].Delete();
      

  13.   

    看来我的问题就是出在这里,我是直接赋值的DataSet,就视为全部都是新增的行,但直接修改会报错:只能在具有 Unchanged DataRowState 的 DataRows 上调用 SetAdded 和 SetModified 。
      

  14.   

    哦,也许会这样,因为我都是直接查询出来后这样操作的,也就是都是在未修改的行上操作,不过对于你的这种情况还有一个更加好的操作方法,就是使用DataTable的Merge方法,你先将涉及到的记录从数据库中查询出来,填充到一个DataTable中,然后设置下该DataTable的主键(必须),最后调用Merge方法将你修改过的DataSet中的Table合并进来。此时它会自动识别并修改RowState,你只要拿这个合并后的DataTable更新到数据库中即可。
      

  15.   

    这个好像是一个好办法,不过这个方法从来没有尝试过,要是有代码就好了。
    就是现有两个DataTable,第1个是数据库现有的数据,第2个是需要回写数据库的数据,怎么设置主键与合并呀?
      

  16.   

    DataTable data1,data2;
    //假设data1为数据库现有的数据,data2为要回写的数据,并且都不为null
    data1.PrimaryKey = new DataColumn[] { data1.Columns["Col1"],data1.Columns["Col2"],data1.Columns["Col3"]};//这里替换为你三个主键的列名
    data1.Merge(data2);//瞧,多简单啊!
      

  17.   

     你的DataSet中的修改的数据部分是如何操作的?如果是新增的行,但是已经存在于数据库中,这不叫修改,仍旧是新增,只有在DataSet中加载了数据库中所有数据后,有过改动的数据行才是修改。那个修改的状态不是通过SqlCommandBuilder来自动识别的,那个只负责创建更新语句,修改状态看DataSet中每个数据行的RowstatusDataSet.Table[0].Rows.New
      

  18.   

    谢谢qldsrx:
    你的方法就是我想要的结果。