SqlDataAdapter.Update批量數據更新


SqlDataAdapter.Update批量數據更新

使用SqlDataAdapter.Update可以方便地對數據庫進行快速、批量數據更新。我們最常用的多條數據更新方法是使用循環多次執行SQL語句或存儲過程,這樣雖然方便,但由於連接和數據傳遞要在服務器和客戶端多次來往,大大增加了整個過程的時間,當數據越大時越明顯!

下面對SqlDataAdapter.Update作個簡單的演示介紹吧。

測試環境:SqlServer2008+VS2010+WinXP

1.建立測試數據庫和表

CREATE DATABASE [TEST]
GO

USE [Test]
GO

CREATE TABLE [Student](
    [SNo] [int] NOT NULL,
    [SName] [nvarchar](50) ,
    [SAge] [int]
) O
GO

2.建立解決方案和項目

使用SqlDataAdapter.Update更新有三種方式,即SqlCommandBuiler自動生成更新,使用配置數據源方式更新,手動編寫命令。

 

SqlCommandBuiler方式:

代碼1:

 private void Form1_Load(object sender, EventArgs e)
        {
            string constr = "server=localhost\\sqlserver2008;initial catalog=test;uid=sa;pwd=123456;";
            SqlConnection conn = new SqlConnection(constr);
            //設置select查詢命令,SqlCommandBuilder要求至少有select命令
            SqlCommand selectCMD = new SqlCommand("select top 0 SNo,SName,SAge from Student", conn);
            DataTable dt = new DataTable();
            SqlDataAdapter sda = new SqlDataAdapter(selectCMD);
            //上面的語句中使用select 0,不是為了查詢出數據,而是要查詢出表結構以向DataTable中填充表結構
            sda.Fill(dt);
            //給DataTable添加10條記錄
            for(int i=1;i<=10;i++)
            dt.Rows.Add(new object[] { i, "aaa"+i, 20+i });
            SqlCommandBuilder scb = new SqlCommandBuilder(sda);
            //執行更新
            sda.Update(dt.GetChanges());
            //使DataTable保存更新
            dt.AcceptChanges();
            
        }

 

//執行后查看表中數據,如圖:


上面我只作了插入操作,那現在將Select中的Top 0 去掉,把表中的數據全部加載到DataTable然后執行刪除和更新操作

代碼2

  private void Form1_Load(object sender, EventArgs e)
        {

    string constr = "server=localhost\\sqlserver2008;initial catalog=test;uid=sa;pwd=123456;";
            SqlConnection conn = new SqlConnection(constr);
            //設置select查詢命令,SqlCommandBuilder要求至少有select命令
            SqlCommand selectCMD = new SqlCommand("select  SNo,SName,SAge from Student", conn);
            DataTable dt = new DataTable();
            SqlDataAdapter sda = new SqlDataAdapter(selectCMD);
            //上面的語句中使用select 0,不是為了查詢出數據,而是要查詢出表結構以向DataTable中填充表結構
            sda.Fill(dt);
            //先更新第1,2條數據的SName和SAge
            dt.Rows[0]["SName"] = "AAA";
            dt.Rows[0]["SAge"] = 33;
            dt.Rows[1]["SName"] = "BBB";
            dt.Rows[1]["SAge"] = 444;
            //然后使用RemoveAt刪除第3,4條數據
            dt.Rows.RemoveAt(2);
            dt.Rows.RemoveAt(3);
            //使用Delete刪除
            //dt.Rows[2].Delete();
            //dt.Rows[3].Delete();
            SqlCommandBuilder scb = new SqlCommandBuilder(sda);
            //執行更新
            sda.Update(dt.GetChanges());
            //使DataTable保存更新
            dt.AcceptChanges();

}

執行后將出錯,錯誤信息“對於不返回任何鍵列信息的 SelectCommand,不支持 UpdateCommand 的動態 SQL 生成。”

出錯原因是建表時沒有設置主鍵。主鍵唯一標識一行數據,SqlCommandBuilder是根據DataTable每行的RowState及對應的主鍵來生成命令的,沒有主鍵就無法確定刪除哪條數據,當然不可能根據其他列來刪除,因為其他列可能重復,這樣會刪除多行數據,很可能執行后不是你想要的結果,這種不確定性的對數據的操作方法,微軟當然不可能提供給你!

那就給表添加主鍵吧

執行如下SQL語句:
alter table student
add constraint PK_Student
primary key(SNo)

 再次執行上面的代碼2.

執行后


我們發現第1,2行數據更新了,但是第3,4行卻沒有刪除。這是怎么回事呢?

先不急,把代碼2中的

 dt.Rows.RemoveAt(2);
  dt.Rows.RemoveAt(3);

注釋掉,同時把

 //dt.Rows[2].Delete();
   //dt.Rows[3].Delete();

的注釋去掉,使之執行Delete方法而不是RemoveAt方法

再看看結果:

第3,4行已經刪除。

原因是:使用RemoveAt或Remove會將數據真正的從DataTable中刪除,而使用Delete則不會,而僅是把當前行的RowState值置為deleted.

前面說過SqlCommandBuilder是根據RowState和主鍵來生成命令的,RemoveAt/Remove把數據刪除了,怎么能找到主鍵和RowState呢?

所以使用SqlCommandBuilder時應該注意的2點:表要有主鍵,應使用delete方法刪除行.

手寫命令方法:

代碼3:

  private void Form1_Load(object sender, EventArgs e)
        {
            string constr = "server=localhost\\sqlserver2008;initial catalog=test;uid=sa;pwd=123456;";
            SqlConnection conn = new SqlConnection(constr);
            //設置select查詢命令
            SqlCommand selectCMD = new SqlCommand("select  SNo,SName,SAge from Student", conn);
            //Insert命令
            SqlCommand insertCMD = new SqlCommand("insert into Student(SNo,SName,SAge) values(@SNo,@SName,@SAge)", conn);
            //Update命令
            SqlCommand updateCMD = new SqlCommand("update Student Set SName=@SName,SAge=@SAge where SNo=@SNo", conn);
            //Delete命令
            SqlCommand deleteCMD = new SqlCommand("delete from Student where SNo=@SNo", conn);

            //給Insert,Update,Delete三個命令添加參數
            SqlParameter paraSNo1, paraSNo2, paraSNo3;//第二個指定參數值的來源,這里的SNo是指DataTable中的列名
            paraSNo1 = new SqlParameter("@SNo", "SNo");
            paraSNo2 = new SqlParameter("@SNo", "SNo");
            paraSNo3 = new SqlParameter("@SNo", "SNo");
            paraSNo1.SourceVersion = DataRowVersion.Current;//指定SourceVersion確定參數值是列的當前值(Current),還是原始值(Original),還是建議值(Proposed)
            paraSNo2.SourceVersion = DataRowVersion.Current;
            paraSNo3.SourceVersion = DataRowVersion.Current;

            SqlParameter paraSName1, paraSName2, paraSName3;
            paraSName1 =  new SqlParameter("@SName", "SName");
            paraSName2 = new SqlParameter("@SName", "SName");
            paraSName3 = new SqlParameter("@SName", "SName");
            paraSName1.SourceVersion = DataRowVersion.Current;
            paraSName2.SourceVersion = DataRowVersion.Current;
            paraSName3.SourceVersion = DataRowVersion.Current;

            SqlParameter paraSAge1, paraSAge2, paraSAge3;
            paraSAge1 = new SqlParameter("@SAge", "SAge");
            paraSAge2 = new SqlParameter("@SAge", "SAge");
            paraSAge3 = new SqlParameter("@SAge", "SAge");
            paraSAge1.SourceVersion = DataRowVersion.Current;
            paraSAge2.SourceVersion = DataRowVersion.Current;
            paraSAge3.SourceVersion = DataRowVersion.Current;

            insertCMD.Parameters.AddRange(new SqlParameter[] { paraSNo1, paraSName1, paraSAge1 });
            updateCMD.Parameters.AddRange(new SqlParameter[] { paraSNo2, paraSName2, paraSAge2 });
            deleteCMD.Parameters.AddRange(new SqlParameter[] { paraSNo3, paraSName3, paraSAge3 });

            DataTable dt = new DataTable();
            SqlDataAdapter sda = new SqlDataAdapter(selectCMD);
            sda.Fill(dt);
            //插入2條數據
            dt.Rows.Add(new object[] { 11, "aa11", 31 });
            dt.Rows.Add(new object[] { 12, "aa12", 32 });


            //先更新第1,2條數據的SName和SAge
            dt.Rows[0]["SName"] = "CCC";
            dt.Rows[0]["SAge"] = 55;
            dt.Rows[1]["SName"] = "DDD";
            dt.Rows[1]["SAge"] = 66;

            //使用Delete刪除第3,4條數據
            dt.Rows[2].Delete();
            dt.Rows[3].Delete();
            SqlCommandBuilder scb = new SqlCommandBuilder(sda);
            //執行更新
            sda.Update(dt.GetChanges());
            //使DataTable保存更新
            dt.AcceptChanges();
        }

執行結果:

可以看到

第SNo為11,12的數據是新增的。

原來SNo為1,2的數據中SName已經從AA,BB更改為CC,DD,另一列SAge從33,44更改為55,66。

原來SNo為5,6也就是第3,4條數據已經被刪除


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM