none
兩個datatable的問題 RRS feed

  • 問題

  • 請教一下各位先進

    假設我有兩個datatable A 與 B 剛開始 A=B

    都是由sql server 某個有primary key的table 假設是 tableA

    但A 與 B 皆 經 過 各 種 途 徑 異 動 之 後 要回寫 tableA
    (有些欄位要用A 有些欄位要用B) 除了使用 

    dataadapter.update外

    是否有辦法藉由程式設計自動產生sql 指令碼 使用 ";" 串接 

    例如有刪除的話就產生 delete tableA where x=......
             新增的話就    insert into tableA(....)values(.....)
             異動的話就    update
             

    • 已移動 璉璉 2009年3月28日 上午 05:48
    2009年3月27日 上午 03:10

解答

  • CommandBuilder 的範例,在線上手冊跟版上的討論都有,搜尋一下就知道了。

    CommandBuilder 要在 SELECT 前就跟 DataAdapter 鍵結,才能幫 DataAdapter 分析 SQL 語法,最後要下:
    DataAdapter.Update
    裡面所需的 DELETE / INSERT / UPDATE ,都會由 CommandBuilder 產生,寫入 DataAdapter 。
    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    2009年3月27日 上午 09:59

所有回覆

  • 也許我比達不夠清楚 我想到一個更好的例子 例如 我依照tableA的schema的格式與順序
    用excel打了一些資料
    用以下的程式碼將excel轉成datatable(第一個欄位是 key值)
    然而這些的資料有可能 或重複 或異動 或刪除了 我該如何用這個datatable與我的tableA同步

    我初步的想法是將 tableA 清空 用truncate table的方式 然後用迴圈將
    datatable一列一列的insert到資料庫的資料表內 這部分我會做

    我遇到的困難是tableA 既有的資料依照key值更新 新增的資料加入到資料表內

       OpenFileDialog og=new OpenFileDialog();
                string fname = "";
                if (og.ShowDialog() == DialogResult.OK)
                {
                  //MessageBox.Show(og.FileName);
                    fname = og.FileName;
                }
                if (! fname.ToString().Contains(".xls"))
                {
                    MessageBox.Show("打開的不是excel");
                    return;
                }
               
            OleDbConnectionStringBuilder builder = new OleDbConnectionStringBuilder();
           // builder.ConnectionString = @"Data Source=" + fname;
            //builder.Add("Provider", "Microsoft.Jet.Oledb.4.0");
            //builder.Add("Extended Properties","Excel 8.0");
            //MessageBox.Show(builder.ConnectionString);
            builder["Provider"] = "Microsoft.Jet.Oledb.4.0";
            builder["Data Source"] = fname;
            builder["Extended Properties"] = "Excel 8.0";
            OleDbConnection objconn = new OleDbConnection(builder.ConnectionString);
            objconn.Open();
            DataTable dt= objconn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
            //取得 excel的第一個 sheet名稱
            MessageBox.Show(dt.Rows[0]["table_name"].ToString());

            string strsql = "select * from [" + dt.Rows[0]["table_name"].ToString() + "]";
            OleDbDataAdapter dap = new OleDbDataAdapter(strsql, objconn);
            DataSet ds=new DataSet();
            dap.Fill(ds);
            dataGridView1.DataSource = ds.Tables[0];

    2009年3月27日 上午 06:27
  • xxxxCommandBuilder 就會自動針對整個 DataTable 產生 SQL 敘述。
    一般是認為 CommandBuilder 的贅詞太多,會影響效能。

    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    2009年3月27日 上午 06:42
  •  可否請大大 協助使用CommandBuilder的範例 我用下面這樣寫 都不會回存到資料庫

               OpenFileDialog og=new OpenFileDialog();
                string fname = "";
                if (og.ShowDialog() == DialogResult.OK)
                {
                 fname = og.FileName;
                }
                if (! fname.ToString().Contains(".xls"))
                {
                    MessageBox.Show("打開的不是excel");
                    return;
                }
              
            OleDbConnectionStringBuilder builder = new OleDbConnectionStringBuilder();
            builder["Provider"] = "Microsoft.Jet.Oledb.4.0";
            builder["Data Source"] = fname;
            builder["Extended Properties"] = "Excel 8.0";
            OleDbConnection objconn = new OleDbConnection(builder.ConnectionString);
            objconn.Open();
            DataTable dt= objconn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
            string strsql = "select * from [" + dt.Rows[0]["table_name"].ToString() + "]";
            OleDbDataAdapter dap = new OleDbDataAdapter(strsql, objconn);
            DataSet ds=new DataSet();
            dap.Fill(ds,"k123");

                opdb op =new opdb();
                SqlDataAdapter dap1 = new SqlDataAdapter();
                dap1.SelectCommand = new SqlCommand("select * from k123", op.getconn());
                SqlCommandBuilder sb = new SqlCommandBuilder(dap1);
                op.getconn().Open();
                dap1.Update(ds,"k123");
                ds.AcceptChanges();
                dataGridView1.DataSource = ds.Tables[0];
                op.getconn().Close();

    class opdb
        {
            public SqlConnection getconn()
            {
                string  strconn = "Data Source=dbtest;Initial Catalog=test;User Id=kent;Password=1111111";
                SqlConnection objconn = new SqlConnection(strconn);
                return objconn;
            }
    }



               
    2009年3月27日 上午 07:44
  •  好久沒寫ADO.NET了
    但怎麼看,你這個都不可能寫回資料庫.
    因為你沒有UpdateCommand.
    你只有 SelectCommand.
    所以再去把ADO.NET的文件讀熟.
    2009年3月27日 上午 08:45
  • CommandBuilder 的範例,在線上手冊跟版上的討論都有,搜尋一下就知道了。

    CommandBuilder 要在 SELECT 前就跟 DataAdapter 鍵結,才能幫 DataAdapter 分析 SQL 語法,最後要下:
    DataAdapter.Update
    裡面所需的 DELETE / INSERT / UPDATE ,都會由 CommandBuilder 產生,寫入 DataAdapter 。
    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    2009年3月27日 上午 09:59
  • 樓主您好 你新建一個dataset然后導入表選中表右鍵屬性 看到數據那一欄
    有6個主要屬性只需要更改 insertcommand,selectcommand,updatecommand 當你需要新添加一列 展開selectcommand 修改commandtext 就可以了然后按照系統提示重新生成就可以了  

    2009年3月27日 上午 10:36
  • 感謝各位大大提供的意見 我自己搞定了

    也許別的大大教訓的是把文件看好就搞定了 不過有時候會沒找到文件 所以上來發問

    希望以後回話的大大 如果知道的話 又不麻煩 就懇請直接寫出來

    不是所有的文件 都可以在短時間內看懂 讓人有個範例可以參考 也是美事一件 您說是吧!

     Dim ds As New DataSet
        Dim da As New SqlDataAdapter
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim OBJCONN As SqlConnection = New SqlConnection("Data Source=PUBLIC\PUBLIC1;Initial Catalog=TEST;User Id=sa;Password=111111;")
            Dim sql As String = "select * from aa"
            da.SelectCommand = New SqlCommand(sql, OBJCONN)
            OBJCONN.Open()
            da.Fill(ds, "test")
            Me.DataGridView1.DataSource = ds.Tables("test")
            OBJCONN.Close()
        End Sub

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim cb As New SqlCommandBuilder(da)
            da.Update(ds, "test")
            ds.Clear()
            da.Fill(ds, "test")
        End Sub

     

    2009年3月27日 下午 04:39
  • 移文至:
    資料存取(ADO.NET與LINQ)


    T.L. Cheng
    2009年3月28日 上午 05:47
  • 或許每個人開發的經驗並不同,很多問題是文件上所沒有的!這點我承認.
    但就我開發流程的整個步驟來說.
    我的整個步驟會去上MSDN 去看有無最新技術可以玩.當然新的技術是建立在舊的技術上.通常一代接一代的研究是比較省力的.但跨代的話,很多東西你會看不懂的,甚至於直接放棄.
    通常新的我會大概看一下,這是做什麼的,怎麼做,對我的工作有沒有用,跟我目前的能不能整合,風險,成本...都初步考量後再決定要不要深入研究.畢竟新的東西太多,工作內容及很多工程師的壓力存在,不可能怎麼都玩.
    初步決定要研究後,也不可任意將舊系統升級到新系統,而是要將所有的文件讀完(這是我要說明的用意),所有的討論區查詢有無相關的議題後,然後對舊系統逐步的更新.
    而以我目前的經驗而言,.net 的每一代週期約3年,每1.5年會有小改版,每次又有ASP.NET,ADO.NET,WPF,WCF...及新的應用,所以通常每個技術你只有2個月的時間運用.半年的時間改版.
    所以ADO.NET 2.x 已經是我好幾年用的東西了. 我用過 ADO.NET 1.x,2.x.DataAccessLibrary 4.x,LINQ To SQL,ADO.NET DataService...
    所以就你的問題,我告訴你,你文件所看到的都是很基礎的.MS的文件都在說明他工具的好,開發的多快.而且很多範例都是用單一Table 或 Table To Table 去做.這種做法,在MSDN或一般外面的參考書都一樣.你只要隨便拉一拉設計表單,他就可以自動新修刪了.當然這沒錯,因為很多都是開發工具產生的.但有時自己修改後,他的工具無法產生後面正確的Code,及你對底層不是很清楚時,你就問為什麼,為什麼了.
    就你這題程式的問題.我可以很清楚的回答,因為剛開始學我也遇到過.你只要用工具產生的,他自動產生Select,Insert,Update,Delete...命令.但因為你自己設SelectCommand,所以說他無法產生Insert,Updata,Delete了.
    為何如此,因為工具笨,人聰明,你用工具設,他知道整個Table結構了,所以他會知道怎麼產生相對應的指令.
    但這些我都不用,因為實務上是行不通的.實務上你要做一個表單,資料都是從很多表單去關聯,去運算然後Show出來的.而在更新回資料庫時,也是經過很複雜的運算,分解後再寫回很多Table的.所以..你的方式還是~但目前對你(大部分的人)都還只能這樣做.
     
    2009年3月29日 上午 02:30
  • 撇開文件不談,你自己有針對你的疑問去 google 過嗎?
    我用你一開始的問題內容,用關鍵字 "自動產生SQL" 去 google 的結果,第一篇就可以解掉你的問題了。

    那請問你做了嗎?

    像你這種問題的範例,網路上是以海量來計算的,但你有去找嗎?
    還是只會在這裡怪別人沒貼範例?
    小人物一枚。
    2009年3月29日 上午 04:31
    版主
  • 回小朱.我的想法是,比較不具經驗的人,可能連自己的問題在哪裡都不知道了,怎麼可能會打你這種這麼專業的敘述去google找那?

    2009年3月29日 上午 05:22
  • 在某論壇中可以拿到 3000 多點專家點數 (光 ASP.NET 就 28xx 點),可以當做不具經驗嗎?


    小人物一枚。
    2009年3月29日 上午 05:44
    版主
  • CommandBuilder 如果不是 Join 的太複雜的,一般的 SELECT 來說,它是可以正確產出對應的 Insert / Update / Delete ,包含 Where 條件都會自動加上去。

    這邊有一篇 OdbcCommandBuilder 的討論:
    [VBNET] CommandBuilder 並未能正確以主鍵值為限制條件
    http://tlcheng.spaces.live.com/blog/cns!145419920BFD55A7!1752.entry
    在多個唯一鍵下,OdbcCommandBuilder 無法正確是別 PK 鍵,而會把最後一個唯一鍵當成 PK 鍵。

    bug 不是我要說的,我要說的是它的確會自己產出對應的 Command ,下面這張圖是摘自該篇:


    所以過去的討論,多半在於 CommandBuilder 產出的 Where 條件過於累贅,有可能會影響到執行 SQL 語法時資料庫的效能,不如自己寫。


    另外針對這句:希望以後回話的大大 如果知道的話 又不麻煩 就懇請直接寫出來

    幫別人找線上手冊跟搜尋是很麻煩的,一方面不知道到底別人是哪個點不懂,另一方面是搜尋本身花時間,又不是每次回文都有足夠的時間可以慢慢回,網友在論壇上回文是義務,不是責任,剛好有空又閒的時候,也許會列網址,正常的話通常只會回方向,一篇簡單的回文,說不定經過回文者看過多份文件的總結,誰有空在那邊條條列參考文獻?
    說難聽一點,自己的問題自己負責,有網友告訴你方向了,你已經不用在茫茫文海中找說明,你應該偷笑了。


    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    2009年3月29日 上午 05:46