桂林网站建设
您的位置: 首页> ADO.net

我要叫喊

学习本类知识需要注意某些知识点,它们之间有些关联

      技术文档
      本站业务
      本类热点
  1. 数据库记录的添...
  2. 取dataview中的行...
  3. 用多活动结果集...
  4. ADO.NET实现应...
  5. ADO.NET2.0的十...
  6. 使用ADO.NET的...
  7. ADO.NET实用经...
  8. 深入分析ADO.N...
  9. ADO.NET的开发...
  10. ADO.NET中的多...
ADO.NET中的多数据表操作浅析—修改
更新数据集

首先需要说明的是我这里去掉了Order Details表,对两个表的操作只是其中的几个字段。

单选框用来选择不同的更新方法。

在DataAccess类中增加两个类成员变量:

     private SqlDataAdapter _customerDataAdapter; //客户数据适配器

     private SqlDataAdapter _orderDataAdapter; //订单数据适配器

customerDataAdapter在构造函数中的初始化为

//实例化_customerDataAdapter

SqlCommand selectCustomerComm = new SqlCommand("GetCustomer",_conn);

selectCustomerComm.CommandType = CommandType.StoredProcedure;

selectCustomerComm.Parameters.Add("@CustomerID",SqlDbType.NChar,5,"CustomerID");

        

SqlCommand insertCustomerComm = new SqlCommand("AddCustomer",_conn);

insertCustomerComm.CommandType = CommandType.StoredProcedure;

insertCustomerComm.Parameters.Add("@CustomerID",SqlDbType.NChar,5,"CustomerID");

insertCustomerComm.Parameters.Add("@CompanyName",SqlDbType.NVarChar,40,"CompanyName");

insertCustomerComm.Parameters.Add("@ContactName",SqlDbType.NVarChar,30,"ContactName");

SqlCommand updateCustomerComm = new SqlCommand("UpdateCustomer",_conn);

updateCustomerComm.CommandType = CommandType.StoredProcedure;

updateCustomerComm.Parameters.Add("@CustomerID",SqlDbType.NChar,5,"CustomerID");

updateCustomerComm.Parameters.Add("@CompanyName",SqlDbType.NVarChar,40,"CompanyName");

updateCustomerComm.Parameters.Add("@ContactName",SqlDbType.NVarChar,30,"ContactName");

             

SqlCommand deleteCustomerComm = new SqlCommand("DeleteCustomer",_conn);

deleteCustomerComm.CommandType = CommandType.StoredProcedure;

deleteCustomerComm.Parameters.Add("@CustomerID",SqlDbType.NChar,5,"CustomerID");

_customerDataAdapter = new SqlDataAdapter(selectCustomerComm);

_customerDataAdapter.InsertCommand = insertCustomerComm;

_customerDataAdapter.UpdateCommand = updateCustomerComm;

_customerDataAdapter.DeleteCommand = deleteCustomerComm;

上面的代码完全可以用设计器生成,觉得有些东西自己写感觉更好,不过代码还是很多。

对于_orderDataAdapter的初始化同上面的差不多,这里我们只看订单增加的处理,下面是存储过程:

CREATE PROCEDURE AddOrder

(

     @OrderID INT OUT,

     @CustomerID NCHAR(5),

     @OrderDate DATETIME

)

AS

INSERT INTO Orders

(

     CustomerID ,

     OrderDate

)

VALUES

(

     @CustomerID ,

     @OrderDate

)

--SELECT @OrderID = @@IDENTITY //使用触发器有可能出现问题

SET @OrderID = SCOPE_IDENTITY()

GO

OrderID自动增长值的获取通过输出参数来完成,这个相当不错,如果使用SqlDataAdapter.RowUpdated事件来处理那效率会很低。

对insertOrderComm对象的定义为:

SqlCommand insertOrderComm = new SqlCommand("AddOrder",_conn);

insertOrderComm.CommandType = CommandType.StoredProcedure;

insertOrderComm.Parameters.Add("@OrderID",SqlDbType.Int,4,"OrderID");

insertOrderComm.Parameters["@OrderID"].Direction = ParameterDirection.Output;

insertOrderComm.Parameters.Add("@OrderDate",SqlDbType.DateTime,8,"OrderDate");

insertOrderComm.Parameters.Add("@CustomerID",SqlDbType.NChar,5,"CustomerID");

在实现数据的更新方法之前我们先来明确一些更新逻辑:

对于标记为删除的行,先删除订单表的数据,再删除客户表的数据;

对于标记为添加的行,先添加客户表的数据,再添加订单表的数据。

(1)实现用获取修改过的DataSet的副本子集来更新数据的方法。

这也是调用Xml Web Service更新数据的常用方法,先来看第一个版本,子集的获取通过DataSet.GetChangs方法来完成。

//使用数据集子集更新数据

public void UpdateCustomerOrders(DatasetOrders ds)

{            

     DataSet dsModified = ds.GetChanges(DataRowState.Modified);//获取修改过的行

     DataSet dsDeleted = ds.GetChanges(DataRowState.Deleted);//获取标记为删除的行

     DataSet dsAdded = ds.GetChanges(DataRowState.Added);//获取增加的行

     try

     {   

         _conn.Open();//先添加客户表数据,再添加订单表数据

         if(dsAdded != null)

         {

              _customerDataAdapter.Update(dsAdded,"Customers");

              _orderDataAdapter.Update(dsAdded,"Orders");

              ds.Merge(dsAdded);

         }

         if(dsModified != null)//更新数据表

         {

              _customerDataAdapter.Update(dsModified,"Customers");

              _orderDataAdapter.Update(dsModified,"Orders");

              ds.Merge(dsModified);

         }

         if(dsDeleted != null)//先删除订单表数据,再删除客户表数据

         {

              _orderDataAdapter.Update(dsDeleted,"Orders");

              _customerDataAdapter.Update(dsDeleted,"Customers");

              ds.Merge(dsDeleted);

         }                 

     }

     catch(Exception ex)

     {

         throw new Exception("更新数据出错",ex);

     }

     finally

     {

         if(_conn.State != ConnectionState.Closed)

              _conn.Close();

     }

}

上面的方法看上去比较清晰,不过效率不会很高,至少中间创建了三个DataSet,然后又进行了多次合并。

(2)另一方法就是引用更新,不创建副本。

相对来说性能会高许多,但是如果用在Web服务上传输的数据量会更大(可以结合两个方法进行改进)。具体的实现就是通过DataTable.Select方法选择行状态来实现。

//引用方式更新数据

public void UpdateCustomerOrders(DataSet ds)

{

     try

     {   

         _conn.Open();

         //先添加客户表数据,再添加订单表数据     _customerDataAdapter.Update(ds.Tables["Customers"].Select("","",DataViewRowState.Added));

     _orderDataAdapter.Update(ds.Tables["Orders"].Select("","",DataViewRowState.Added));

     //更新数据表

     _customerDataAdapter.Update(ds.Tables["Customers"].Select("","",DataViewRowState.ModifiedCurrent));

     _orderDataAdapter.Update(ds.Tables["Orders"].Select("","",DataViewRowState.ModifiedCurrent));

//先删除订单表数据,再删除客户表数据

     _orderDataAdapter.Update(ds.Tables["Orders"].Select("","",DataViewRowState.Deleted));

     _customerDataAdapter.Update(ds.Tables["Customers"].Select("","",DataViewRowState.Deleted));           

     }

     catch(Exception ex)

     {

         throw new Exception("更新数据出错",ex);

     }

     finally

     {

         if(_conn.State != ConnectionState.Closed)

              _conn.Close();

     }

}

结合上面的两个方法我们可想到调用Web Service有更合理的方法来完成。

(3)使用事务

public void UpdateCustomerOrdersWithTransaction(DataSet ds)

{

     SqlTransaction trans = null;

     try

     {   

         _conn.Open();

         trans = _conn.BeginTransaction();

         _customerDataAdapter.DeleteCommand.Transaction = trans;

         _customerDataAdapter.InsertCommand.Transaction = trans;

         _customerDataAdapter.UpdateCommand.Transaction = trans;

         _orderDataAdapter.DeleteCommand.Transaction = trans;

         _orderDataAdapter.InsertCommand.Transaction = trans;

         _orderDataAdapter.UpdateCommand.Transaction = trans;

     _customerDataAdapter.Update(ds.Tables["Customers"].Select("","",DataViewRowState.Added));

                   _orderDataAdapter.Update(ds.Tables["Orders"].Select("","",DataViewRowState.Added));

     _customerDataAdapter.Update(ds.Tables["Customers"].Select("","",DataViewRowState.ModifiedCurrent));

     _orderDataAdapter.Update(ds.Tables["Orders"].Select("","",DataViewRowState.ModifiedCurrent));

     _orderDataAdapter.Update(ds.Tables["Orders"].Select("","",DataViewRowState.Deleted));

     _customerDataAdapter.Update(ds.Tables["Customers"].Select("","",DataViewRowState.Deleted)); 

          trans.Commit();

     }

     catch(Exception ex)

     {

         trans.Rollback();

         throw new Exception("更新数据出错",ex);

     }

     finally

     {

         if(_conn.State != ConnectionState.Closed)

              _conn.Close();

     }

}

最后让我们来看看窗体的按钮更新事件的代码:

private void buttonUpdate_Click(object sender, System.EventArgs e)

{

              //提交编辑数据

     this.BindingContext[this._ds].EndCurrentEdit();

    

     if(radioButtonRef.Checked == true)//引用方式更新

         _dataAccess.UpdateCustomerOrders((DataSet)_ds);

     else if(radioButtonTrans.Checked == true)//启用事务更新数据表

         _dataAccess.UpdateCustomerOrdersWithTransaction((DataSet)_ds);

     else

     {

         DatasetOrders changedData = (DatasetOrders)_ds.GetChanges();

         if(radioButtonWeb.Checked == true)//Web服务的更正更新

         {                     

              _dataAccess.UpdateCustomerOrders((DataSet)changedData);

         }

         else//创建副本合并方式更新

         {                 

              _dataAccess.UpdateCustomerOrders(changedData);

         }

         //去除订单表中添加的虚拟行

         foreach(DataRow row in _ds.Orders.Select("","",DataViewRowState.Added))

              _ds.Orders.RemoveOrdersRow((DatasetOrders.OrdersRow)row);

         //去除客户表中添加的虚拟行

         foreach(DataRow row in _ds.Customers.Select("","",DataViewRowState.Added))

              _ds.Customers.RemoveCustomersRow((DatasetOrders.CustomersRow)row);

         _ds.Merge(changedData);

     }

     //提交数据集状态

     _ds.AcceptChanges();

}