对ADO.net 数据存取的一些测试心得:
1. 使用控件如GridControl GridView的DataSource创建DataSet与手动创建的DataSet效果是相同的,在项目中应使用强类型的DataSet
2.更新数据时,需指定4种SqlCommand,InsertCommand、DeleteCommand、UpdateCommand、SelectCommand 还可以使用SqlCommandBuilder为SqlDataAdapter自动生成4个SqlCommand。
使用方法: 在创建SqlCommandBuilder时将SqlDataAdapter传入即可,即 SqlCommandBuilder scb = new SqlCommandBuilder(da);
3.当手工为DataAdapter指定InsertCommand:
string strSql = "Insert into Employees(LastName,FirstName,Title,TitleOfCourtesy,Address,City,Region) " + "Values(@LastName,@FirstName,@Title,@TitleOfCourtesy,@Address,@City,@Region)" + "Select 222 as EmployeeID,LastName,FirstName,Title,TitleOfCourtesy,Address,City,Region "+ " from Employees Where LastName = @LastName and FirstName = @FirstName"; da.InsertCommand = new SqlCommand(strSql, conn); da.InsertCommand.Parameters.Add("@LastName", SqlDbType.NChar,20,"LastName"); da.InsertCommand.Parameters.Add("@FirstName", SqlDbType.NChar, 20, "FirstName"); da.InsertCommand.Parameters.Add("@Title", SqlDbType.NChar, 20, "Title"); da.InsertCommand.Parameters.Add("@TitleOfCourtesy", SqlDbType.NChar, 20, "TitleOfCourtesy"); da.InsertCommand.Parameters.Add("@Address", SqlDbType.NChar, 20, "Address"); da.InsertCommand.Parameters.Add("@City", SqlDbType.NChar, 20, "City"); da.InsertCommand.Parameters.Add("@Region", SqlDbType.NChar, 20, "Region"); da.InsertCommand.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord;
此处有需要注意: 1. InsertCommand.UpdatedRowSource 属性有4个 分别是:Both、FirstReturnedRecord、None、OutputParameters. Both是既用每一行记录也使用传出的参数刷新table
- 注意在insertCommand中还有一条Select的语句,用来刷新DataSet中的表在更新后的数据。而且这条Select所返回的记录需要在
- DataAdapter.RowUpdated事件中的参数取得。
- RowUpdated事件,此事件会根据每行记录而触发。
void da_RowUpdated(object sender, SqlRowUpdatedEventArgs e) { if (e.StatementType == StatementType.Insert && e.Status == UpdateStatus.Continue) { string sql = "select @EmployeeID = @@IDENTITY"; SqlCommand cmdRefresh = new SqlCommand(sql,e.Command.Connection); SqlParameter p = cmdRefresh.Parameters.Add("@EmployeeID", SqlDbType.Int); p.Direction = ParameterDirection.Output; cmdRefresh.ExecuteNonQuery(); e.Row["EmployeeID"] = cmdRefresh.Parameters["@EmployeeID"].Value; //gridView1.RefreshRow(); //northwindDataSet.Employees.Rows[gridView1.FocusedRowHandle]["EmployeeID"] = cmdRefresh.Parameters["@EmployeeID"].Value; } } 另外,由于OrderId是自增列,如果要刷新此列,需要用@@IDENTITY 或SCOPE_IDENTITY()获得。
这个事件中,把由InsertCommand的select语句传来的记录指给e.Row中指定列,就完成了前台记录刷新。
4. 再看一代码,用来保存数据的
private void button1_Click(object sender, EventArgs e) { if (northwindDataSet.HasChanges(DataRowState.Added) || northwindDataSet.HasChanges(DataRowState.Modified)) { NorthwindDataSet.EmployeesDataTable dtUpdate = northwindDataSet.Employees.GetChanges(DataRowState.Added) as NorthwindDataSet.EmployeesDataTable; if (dtUpdate != null) da.Update(northwindDataSet.Employees.Select("","",DataViewRowState.Added)); dtUpdate = northwindDataSet.Employees.GetChanges(DataRowState.Modified) as NorthwindDataSet.EmployeesDataTable; if (dtUpdate != null) da.Update(dtUpdate); northwindDataSet.Employees.AcceptChanges(); //MessageBox.Show(northwindDataSet.Employees.Rows[gridView1.FocusedRowHandle]["FirstName"].ToString()); } }此处也要注意,先前使用了dtUpdate传给da.update()结果导致RowUpdated方法中刷新记录失效,因为这里将GridView所绑定的表
- 的记录筛选了一份放在dtUpdate之中,从而导致RowUpdated方法将dtUpdate的记录刷新。所以在此处,我将 da.Update(dtUpdate)换成了 da.Update(northwindDataSet.Employees.Select(…)) 成功刷新记录。
每次更新完成之后,应调用一次 northwindDataSet.Employees.AcceptChanges(); 将Dataset中的每一行状态恢复。
- 还要注意的是,如果使用DataAdapter.Update删除操作时,需要看看EmployeeID有没有刷新,如果此主键未刷新那么将导致删除失败。 这是因为,Delete时候需要靠此主键做为WHere条件.
使用WebService更新数据,那么可以用.Employees.GetChanges(DataRowState.Modified) 将表中挂起的记录取出再传回WebService,这样可以减少网络数据量. 而经过更新的记录可以用DataSet.Merge方法合并.再显示到前台界面上.
- 关于DataSet.Merge暂未测试。
strSQL = "UPDATE OrderDetailsWithTimestamp " + " SET OrderID = @OrderID_New, ProductID = @ProductID_New, " + " Quantity = @Quantity_New, UnitPrice = @UnitPrice_New " + " WHERE OrderID = @OrderID_Old AND ProductID = @ProductID_Old " + " AND TimestampColumn = @TimestampColumn_Old"; da.UpdateCommand = new SqlCommand(strSQL, cn); da.UpdateCommand.Parameters.Add("@OrderID_New", SqlDbType.Int, 0, "OrderID"); da.UpdateCommand.Parameters.Add("@ProductID_New", SqlDbType.Int, 0, "ProductID"); da.UpdateCommand.Parameters.Add("@Quantity_New", SqlDbType.SmallInt, 0, "Quantity"); da.UpdateCommand.Parameters.Add("@UnitPrice_New", SqlDbType.Money, 0, "UnitPrice"); da.UpdateCommand.Parameters.Add("@OrderID_Old", SqlDbType.Int, 0, "OrderID").SourceVersion = DataRowVersion.Original; da.UpdateCommand.Parameters.Add("@ProductID_Old", SqlDbType.Int, 0, "ProductID").SourceVersion = DataRowVersion.Original; da.UpdateCommand.Parameters.Add("@TimestampColumn_Old", SqlDbType.Timestamp, 8, "TimestampColumn").SourceVersion = DataRowVersion.Original; da.UpdateCommand.UpdatedRowSource = UpdateRowSource.None;
static void HandleRowUpdated_RefreshAfterUpdate(object sender, SqlRowUpdatedEventArgs e) { if (e.Status == UpdateStatus.Continue && (e.StatementType == StatementType.Insert || e.StatementType == StatementType.Update)) { string strSQL; strSQL = "SELECT @Quantity = Quantity, @UnitPrice = UnitPrice, " + " @TimestampColumn = TimestampColumn FROM OrderDetailsWithTimestamp " + " WHERE OrderID = @OrderID AND ProductID = @ProductID"; SqlCommand cmd = new SqlCommand(strSQL, e.Command.Connection); cmd.Parameters.Add("@Quantity", SqlDbType.SmallInt).Direction = ParameterDirection.Output; cmd.Parameters.Add("@UnitPrice", SqlDbType.Money).Direction = ParameterDirection.Output; cmd.Parameters.Add("@TimestampColumn", SqlDbType.Timestamp).Direction = ParameterDirection.Output; cmd.Parameters.AddWithValue("@OrderID", e.Row["OrderID"]); cmd.Parameters.AddWithValue("@ProductID", e.Row["ProductID"]); cmd.ExecuteNonQuery(); e.Row["Quantity"] = cmd.Parameters["@Quantity"].Value; e.Row["UnitPrice"] = cmd.Parameters["@UnitPrice"].Value; e.Row["TimestampColumn"] = cmd.Parameters["@TimestampColumn"].Value; }