我是用C#写的一个通用数据绑定自动更新类,主要时间将任何一个带主键的表绑定到一个DataGrid上,在DataGrid上添加删除修改后,保存时使用DataAdapter的update方法自动更新到数据库中.
这个程序是很好用的,并且已经使用很长时间,而且比较稳定,后来又改进使用了EnterpriseLibrary也是一样的功能,也是好使的
现在遇到一个新问题就是:我发现原先的DataAdapter的Update方法在更新前效验了并发性问题,
即如果update在执行时,发现目标数据库中的本行数据和已经读取到DataGrid中的数据有任何一处不同时(注意:不仅仅是主键不同,非主键不同也算)就会提示并发性错误
而我现在的需求是,能不能关闭DataAdapter的update的完整验证,而只是验证主键列是否存在,如果主键验证通过,其它的列即使不一样也能更新成功,即用新数据强行覆盖数据库的数据
基本原理就是原先的update执行的语句应该是这样:
update table set primaryCol=newValue1,col1=newValue2 where primaryCol=oldValue1,col1=oldValue2 
而我想让它变成:
update table set primaryCol=newValue1,col1=newValue2 where primaryCol=oldValue1请高手赐教,盼回复

解决方案 »

  1.   

    DataAdapter 更新,感觉很鸡肋,做的项目没用过一次。
      

  2.   

    自己写DataAdapter的InsertCommand、UpdateCommand 或 DeleteCommand
    下面的例子摘自MSDN SqlDataAdapter adapter = new SqlDataAdapter();    // Create the SelectCommand.
        SqlCommand command = new SqlCommand("SELECT * FROM Customers " +
            "WHERE Country = @Country AND City = @City", connection);    // Add the parameters for the SelectCommand.
        command.Parameters.Add("@Country", SqlDbType.NVarChar, 15);
        command.Parameters.Add("@City", SqlDbType.NVarChar, 15);    adapter.SelectCommand = command;    // Create the InsertCommand.
        command = new SqlCommand(
            "INSERT INTO Customers (CustomerID, CompanyName) " +
            "VALUES (@CustomerID, @CompanyName)", connection);    // Add the parameters for the InsertCommand.
        command.Parameters.Add("@CustomerID", SqlDbType.NChar, 5, "CustomerID");
        command.Parameters.Add("@CompanyName", SqlDbType.NVarChar, 40, "CompanyName");    adapter.InsertCommand = command;    // Create the UpdateCommand.
        command = new SqlCommand(
            "UPDATE Customers SET CustomerID = @CustomerID, CompanyName = @CompanyName " +
            "WHERE CustomerID = @oldCustomerID", connection);    // Add the parameters for the UpdateCommand.
        command.Parameters.Add("@CustomerID", SqlDbType.NChar, 5, "CustomerID");
        command.Parameters.Add("@CompanyName", SqlDbType.NVarChar, 40, "CompanyName");
        SqlParameter parameter = command.Parameters.Add(
            "@oldCustomerID", SqlDbType.NChar, 5, "CustomerID");
        parameter.SourceVersion = DataRowVersion.Original;    adapter.UpdateCommand = command;    // Create the DeleteCommand.
        command = new SqlCommand(
            "DELETE FROM Customers WHERE CustomerID = @CustomerID", connection);    // Add the parameters for the DeleteCommand.
        parameter = command.Parameters.Add(
            "@CustomerID", SqlDbType.NChar, 5, "CustomerID");
        parameter.SourceVersion = DataRowVersion.Original;    adapter.DeleteCommand = command;
      

  3.   

    那你可以使用自己写的UpdateCommand对象赋值给
    DataAdapter.UpdateCommand 属性呀。
      

  4.   

    onload()
    try
                {
                    this.oleDbConnection1.Close();
                    this.oleDbConnection1.ConnectionString = constr+Path+@"Data\"+DBName;
                    this.oleDbConnection1.Open();
                    this.oleDbDataAdapter1.SelectCommand.Connection = this.oleDbConnection1;
                    this.oleDbCommandBuilder1 = new OleDbCommandBuilder(this.oleDbDataAdapter1);                this.oleDbDataAdapter1.SelectCommand.CommandText = "select AlarmTypeIndex as 编号,"+
                        "DeviceName as 设备名称,AlarmTypeName as 告警名称 from AlarmType order by AlarmTypeIndex";
                    
                    this.oleDbDataAdapter1.SelectCommand.ExecuteNonQuery();
                    this.dataSet1.Clear();
                    this.oleDbDataAdapter1.Fill(dataSet1, "AlarmType");
                    this.dataGridView1.DataSource = this.dataSet1.Tables["AlarmType"];                DataColumn[] PrimaryKey = new DataColumn[] { this.dataSet1.Tables[0].Columns[0] };
                    this.dataSet1.Tables[0].PrimaryKey = PrimaryKey;//设置表的主键信息                this.dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
                    this.dataGridView1.CellClick += this.ListSelectedRowInfo;//设置选中模式            }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                    if (this.oleDbConnection1.State == ConnectionState.Open)
                    {
                        this.oleDbConnection1.Close();
                    }
                }
    btnclick;
                try
                {
                    this.oleDbDataAdapter1.Update(this.dataSet1, "AlarmType");
                    MessageBox.Show("保存成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
    private void BtnQuery_Click(object sender, EventArgs e)
            {
                this.oleDbDataAdapter1.SelectCommand.CommandText = "select AlarmTypeIndex as 编号," +
                     "DeviceName as 设备名称,AlarmTypeName as 告警名称 from AlarmType order by AlarmTypeIndex";            this.oleDbDataAdapter1.SelectCommand.ExecuteNonQuery();
                this.dataSet1.Clear();
                this.oleDbDataAdapter1.Fill(dataSet1, "AlarmType");
                this.dataGridView1.DataSource = this.dataSet1.Tables["AlarmType"];            DataColumn[] PrimaryKey = new DataColumn[] { this.dataSet1.Tables[0].Columns[0] };
                this.dataSet1.Tables[0].PrimaryKey = PrimaryKey;//设置表的主键信息        }
    代码很乱,是自己写的
      

  5.   

    楼上几位的方法我知道,可能我没说清楚
    我之所以用Adapter,是因为利用了他的CommandBuilder功能
    因为需要更新的表上千个,根本不可能一个个写update语句,而且还有新表和未知的表
    整个系统是基于通用,反射的理念,必须自动生成update命令,不能自己写,连表名都是动态的参数
    现在Adapter的CommandBuilder已经做的很好了,功能都是好用的,只是我想修改一下实现过程,以满足灵活的需要
      

  6.   

    楼主,不要从死盯着DbDataAdapter,它是无辜的,你应该"修理"DbCommandBuilder:SqlCommandBuilder sqlCommandBuilder=new SqlCommandBuilder()//先不附SqlDataAdapter
    sqlCommandBuilder.ConflictOption=ConflictOption.OverwriteChanges;//关键,where子句只包含PK
    sqlCommandBuilder.Adapter=sqlDataAdapter  //到这里才把sqlCommandBuilder和sqlDataAdapter关联
    //It is OK!