ASP.net 实现批量更新/插入

 

.SqlCommandBuilder 实现批量更新/插入

  1.功能:

  可以实现你对DataSetUI层做任意操作后,直接丢给这个方法,这个方法就可以自动把你的修改更新到数据库中,而没必要每次都更新到数据库

2.使用方法

/// <summary>

/// 直接通过DataSet更新数据库表

/// </summary>

/// <param name="ds"></param>

/// <param name="strTblName">ds中要更新的表名</param>

/// <param name="strConnection"></param>

/// <returns></returns>

public int UpdateByDataSet(DataSet ds,string strTblName,string strConnection)
  {
   try
  {
   SqlConnection  conn = new SqlConnection(strConnection));
        
   SqlDataAdapter myAdapter = new SqlDataAdapter();
   SqlCommand myCommand = new SqlCommand("select  * from "+strTblName),(SqlConnection)this.conn);   
   myAdapter.SelectCommand = myCommand;
   SqlCommandBuilder myCommandBuilder = new SqlCommandBuilder(myAdapter);    
   myAdapter.Update(ds,strTblName); 
 
   return 0;
 }
 catch(BusinessException errBU)
 { 
   throw errBU;
 }  
 catch(Exception err)
 { 
   throw new BusinessException(err);
 }
}

说明:1. 用类似下面的语句可以实现批量的插入

System.Data.DataRow dr = ds.Tables[0].NewRow();

dr[0] = "222";

dr[1] = "test";

ds.Tables[0].Rows.Add(dr);

2. “select * from “+strTblName是一定要的,主要是告诉 SqlDataAdapter更新哪个表.不过可以用top 1 来提高效率(个人认为)

3.如果没有myCommandBuilder那句就会出错.  

一般是这样的,如果用设计器将SqlDataAdapter拖到页面中使用时,不会出现这种情况,因为系统会自动生成SqlDataAdapter的属性命令,比如:  .UpdateCommane insertCommand   selectCommand等。但是有些程序员不喜欢用设计器,或者是有些地方没必要拖动SqlDataAdapter这么个庞大物来实现,那么SqlDataAdapter就不会自动生成相关的查询或更新语句了.所以当执行到SqlDataAdapter.Update(ds)语句时,SqlDataAdapter桥接器不知道更新哪个表.不报错了

  4.什么时候用?

    a. 有时候需要缓存的时候,比如说在一个商品选择界面,选择好商品,并且进行编辑/删除/更新后,最后一并交给数据库,而不是每一步操作都访问数据库,因为客户选择商品可能进行n次编辑/删除更新操作,如果每次都提交,不但容易引起数据库冲突,引发错误,而且当数据量很大时在用户执行效率上也变得有些慢

    b.有的界面是这样的有的界面是这样的,需求要求一定用缓存实现,确认之前的操作不提交到库,点击页面专门提交的按钮时才提交商品选择信息和商品的其它信息. 我经常遇到这样的情况

    c.有些情况下只往数据库里更新,不读取. 也就是说没有从数据库里读,SqlDataAdapter也就不知道是更新哪张表了,调用Update就很可能出错了。这样的情况下可以用SqlCommandBuilder .
        

  5. 注意点:

  1.只能更新一个表,不能更新两个或两个以上相关联的表
  2.表中必须有主键
  3.更新的表中字段不能有image类型的

  6.优点:

    节省代码量,节省时间,这个方法可以代替所有的更新/插入操作语句

  7.缺点:
  访问两次数据库(select * TableName,就是这句,要确认是哪个表,除非是很大的数据量,一般是感觉不到的),效率有些慢。但是可以通过设置UpdateBatchSize的大小来优化程序.

.自己写SqlCommand 实现批量更新/插入

摘自MSDN:

  在以前版本的 ADO.NET 中,使用 DataSet 中的更改来更新数据库时,DataAdapter Update 方法每次更新数据库的一行。因为该方法循环访问指定 DataTable 中的行,所以,会检查每个 DataRow,确定是否已修改。如果该行已修改,将根据该行的 RowState 属性值调用相应的 UpdateCommandInsertCommand DeleteCommand。每一次行更新都涉及网络与数据库之间的双向数据传输。

  在 ADO.NET 2.0 中,DataAdapter 公开了 UpdateBatchSize 属性。将 UpdateBatchSize 设置为正整数值将使对数据库的更新以指定大小的批次进行发送。例如,如果将 UpdateBatchSize 设置为 10,会将 10 个独立的语句组合在一起并作为一批提交。将 UpdateBatchSize 设置为 0 将导致 DataAdapter 使用服务器可以处理的最大批次的大小。如果将其设置为 1,则禁用批量更新,因为此时每次发送一行。

  执行非常大的批次可能会降低性能。因此,在实现应用程序之前,应测试最佳的批次大小设置。

  使用 UpdateBatchSize 属性

  启用了批量更新后,DataAdapter UpdateCommandInsertCommand DeleteCommand UpdatedRowSource 属性值应设置为 None OutputParameters。在执行批量更新时,命令的 FirstReturnedRecord Both UpdatedRowSource 属性值无效。

  下面的过程演示如何使用 UpdateBatchSize 属性。该过程采用两个参数,一个 DataSet 对象,其中包含代表 Production.ProductCategory 表中的 ProductCategoryID Name 字段的列,一个代表批次大小的整数(批次中的行数)。该代码创建一个新的 SqlDataAdapter 对象,设置其 UpdateCommandInsertCommand DeleteCommand 属性。该代码假定 DataSet 对象已修改了行。它设置 UpdateBatchSize 属性并执行更新。

protected void btnUpdateAddress_Click(object sender, EventArgs e)
    {
        SqlDataAdapter EmpAdapter = new SqlDataAdapter();
        DataTable EmpDT = new DataTable();
        SqlConnection DBConSelect = new SqlConnection();
        SqlConnection DBConUpdate = new SqlConnection();
        SqlCommand SelectCommand = new SqlCommand();
        SqlCommand UpdateCommand = new SqlCommand();

        // Using different connection objects for select and updates from the
        // Northwind database.
        DBConSelect.ConnectionString =
          ConfigurationManager.ConnectionStrings["DSN_NorthWind"].ConnectionString;
        DBConUpdate.ConnectionString =
          ConfigurationManager.ConnectionStrings["DSN_NorthWind"].ConnectionString;

        // Reading all records from the Employees table
        SelectCommand.CommandText = "SELECT top 500 * FROM EMPLOYEES";
        SelectCommand.CommandType = CommandType.Text;
        SelectCommand.Connection = DBConSelect;

        UpdateCommand.CommandText = " UPDATE EMPLOYEES SET Address=@Address, " +
                                    "City=@City, Region=@Region, Country=@Country";

        UpdateCommand.CommandType = CommandType.Text;
        UpdateCommand.Connection = DBConUpdate;

        SqlParameter AddressParam;
        AddressParam = new SqlParameter("@Address",
           SqlDbType.VarChar, 15, "Address");

        SqlParameter CityParam;
        CityParam = new SqlParameter("@City", SqlDbType.VarChar, 15, "City");

        SqlParameter RegionParam;
        RegionParam = new SqlParameter("@Region", SqlDbType.VarChar, 15, "Region");

        SqlParameter CountryParam;
        CountryParam = new SqlParameter("@Country",
           SqlDbType.VarChar, 15, "Country");

        UpdateCommand.Parameters.Add(AddressParam);
        UpdateCommand.Parameters.Add(CityParam);
        UpdateCommand.Parameters.Add(RegionParam);
        UpdateCommand.Parameters.Add(CountryParam);

        // Setting up Data Adapter with the Select and Update Commands
        // The Select command will be used to retrieve all employee
        // information from the Northwind database and the Update command
        // will be used to save changes back to the database
        EmpAdapter.SelectCommand = SelectCommand;
        EmpAdapter.UpdateCommand = UpdateCommand;

        EmpAdapter.Fill(EmpDT);

        DBConSelect.Close();

        // Looping through all employee records and assigning them the new
        // address
        foreach (DataRow DR in EmpDT.Rows)
        {
            DR["Address"] = "4445 W 77th Street, Suite 140";
            DR["City"] = "Edina";
            DR["Region"] = "Minnesota";
            DR["Country"] = "USA";
        }

        // Adding an event handler to listen to the RowUpdated event.
        // This event will will fire after each batch is executed
        EmpAdapter.RowUpdated +=  new SqlRowUpdatedEventHandler(OnRowUpdated);

        lblCounter.Text = "";

        EmpAdapter.UpdateBatchSize = 100;

        // It is important to set this property for batch processing of
        // updated records since batch updates are incapable of
        // updating the source with changes from the database
        UpdateCommand.UpdatedRowSource = UpdateRowSource.None;

        try
        {
            DBConUpdate.Open();
            EmpAdapter.Update(EmpDT);
        }
        catch (Exception ex)
        {
            lblCounter.Text += ex.Message + "<Br>";
        }
        finally
        {
            if (DBConUpdate.State == ConnectionState.Open)
            {
                DBConUpdate.Close();
            }
        }
    }

    private void OnRowUpdated(object sender, SqlRowUpdatedEventArgs args)
    {
        lblCounter.Text += "Batch is processed till row number = " +
           args.RowCount.ToString() + "<br>";
    }

 

posted on 2007-10-19 10:09  LongSky  阅读(534)  评论(0编辑  收藏  举报

导航