我是用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请高手赐教,盼回复
这个程序是很好用的,并且已经使用很长时间,而且比较稳定,后来又改进使用了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请高手赐教,盼回复
下面的例子摘自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;
DataAdapter.UpdateCommand 属性呀。
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;//设置表的主键信息 }
代码很乱,是自己写的
我之所以用Adapter,是因为利用了他的CommandBuilder功能
因为需要更新的表上千个,根本不可能一个个写update语句,而且还有新表和未知的表
整个系统是基于通用,反射的理念,必须自动生成update命令,不能自己写,连表名都是动态的参数
现在Adapter的CommandBuilder已经做的很好了,功能都是好用的,只是我想修改一下实现过程,以满足灵活的需要
sqlCommandBuilder.ConflictOption=ConflictOption.OverwriteChanges;//关键,where子句只包含PK
sqlCommandBuilder.Adapter=sqlDataAdapter //到这里才把sqlCommandBuilder和sqlDataAdapter关联
//It is OK!