none
vb2008 DataGridView存入sql問題 (不同sql主機 且DataGridView有變動---新增欄位) RRS feed

  • 問題

  • 親愛的各位大大有個DataGridView存入資料庫的問題想請教各位:
       我從A sql主機取得某些資料放在DataGridview1中,然後用拷貝的方式拷貝到DataGridView2,然後又在DataGridview2內新增幾個欄位。那幾個新增的欄位(從採購單別到詢價人員,其中詢價日期是取系統日期;詢價人員是取電腦使用者名稱)其它是要給user填入資料。當Datagridview2填完後,我new了一個myDatatable3將myDatatable3資料存入另一部主機就是B Sql主機,所以我又new了新的sqlconnection。

    問題1.該如何將新的資料存入B Sql主機?
    問題2.如何判斷從DataGridview1拷貝到DataGridview2的資料是否有重複?
    問題3.myDatatable3存入B sql主機在存的過程中如何知到主機中是否已有相同的資料??
    問題4.每按一次copy的Button,從DataGridview1拷背到DataGridView2時自動去新增詢價人員名稱跟詢價日期到DataGridview2的兩個cell中
    請問各位大大這些程式碼該如何寫?
    程式碼如下:
    Public Class Form2
        Dim conn1 As New SqlConnection  \\為了存入B Sql主機所做的新的連線
        Dim strDbCon1 As String
        Dim ds1 As New DataSet
        Dim command As SqlCommand
        Dim myDatatable3 As New DataTable

        Dim conn As SqlConnection   \\ A Sql主機的連線
        Dim strDbCon As String
        Dim ds As New DataSet
        Dim cmd As SqlCommand
        Dim sqlstr As String
        Dim myDatatable1 As New DataTable
        Dim myDatatable2 As New DataTable

        Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
            Close()
        End Sub

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            strDbCon = "Persist Security Info=False;User ID=sa;pwd=dsc;Initial Catalog=Grandex;Data Source=192.195.68.19"
            conn = New SqlConnection(strDbCon)
            conn.Open()
            Dim bs As New SqlDataAdapter("SELECT PURTA.TA001, PURTB.TB002, PURTB.TB003, PURTA.TA012,PURTA.TA003, PURTB.TB004, PURTB.TB005, PURTB.TB007,PURTB.TB016, PURTB.TB009 FROM PURTA INNER JOIN PURTB ON PURTA.TA001 = PURTB.TB001 AND PURTA.TA002 = PURTB.TB002 Where PURTA.TA001='" + TextBox1.Text + "' AND PURTB.TB002='" + TextBox2.Text + "' ", strDbCon)
            bs.Fill(ds, "PURTA")
            'DataGridView1.DataSource = ds.Tables("PURTA")
            DataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect
            DataGridView2.SelectionMode = DataGridViewSelectionMode.FullRowSelect
            myDatatable1 = ds.Tables("PURTA")
            DataGridView1.DataSource = myDatatable1
            myDatatable2 = myDatatable1.Clone
            TextBox3.Text = Convert.ToString(DataGridView1.Rows(0).Cells(3).Value)
            TextBox4.Text = Convert.ToString(DataGridView1.Rows(0).Cells(4).Value)
            Button1.Enabled = False
            myDatatable2.Columns.Add("採購單別")
            myDatatable2.Columns.Add("採購單號")
            myDatatable2.Columns.Add("採購序號")
            myDatatable2.Columns.Add("供應商")
            myDatatable2.Columns.Add("單價")
            myDatatable2.Columns.Add("詢價數量")
            myDatatable2.Columns.Add("交貨地")
            myDatatable2.Columns.Add("詢價日期")
            myDatatable2.Columns.Add("詢價人員")
            DataGridView2.DataSource = myDatatable2

        End Sub

        Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            TextBox5.Text = Environment.GetEnvironmentVariable("UserNAME")
            TextBox6.Text = Convert.ToString(System.DateTime.Now.ToString("yyyy/MM/dd"))

        End Sub

        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

            RowCopy(DataGridView1, DataGridView2)
        End Sub

        Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click //存到B SQL主機
            myDatatable3 = DataGridView2.DataSource
            strDbCon1 = "Persist Security Info=False;User ID=sa;pwd=dsc;Initial Catalog=Gdex;Data Source=192.195.68.50"
            conn1 = New SqlConnection(strDbCon1)
            conn1.Open()
             這一段不知怎麼寫才能存入到B Sql主機,且資料不會重覆存入

        End Sub
    End Class

    ps:以申請單號為主要判別依據

    2009年11月23日 上午 08:45

解答

  • 因為要判斷是否重覆,這一點其實只能做苦工.
    一種像心冷大講的, 針對鍵值直接Delete, 再新增,
    這時如果要新增的資料很多, 可以考慮用 [SqlBulkCopy 類別 ] 從DataTable的執行個體做大量複製
    另外一種就是用[SqlDataReader 類別 ]或[SqlCommand. ExecuteScalar 方法 ]
    針對目標資料庫Select 看看有沒有重覆的資料, 如沒有則Insert, 如有則Update
    也許其它前輩會有更好的解法.


    學而不思則罔, 思而不學則殆.
    如果你一直都看不懂、不想學習看懂、抗拒看懂MSDN Library的話,那你最好放棄想要寫好程式這件事
    如果你自私地不肯回饋與分享,那別人為何要花時間回答你的問題?
    • 已標示為解答 MichaelTsai10 2009年11月24日 上午 09:52
    2009年11月23日 下午 01:16
    版主

  •     向來我都採用 Bill 大說的第二種方法, 例如:

        Public Function AddNewUser(ByVal UserID As String, ByVal Password As String, ByVal NeedEncPwd As Boolean, _
                                ByVal UserName As String) As Boolean

            If goDB.Open = False Then Exit Function '確認資料庫連線

            Dim MsgTtl As String = "新增使用者"
            Dim intRet As Integer

            Try

               ///

                Using cmd As SqlClient.SqlCommand = goDB.Conn.CreateCommand
                    Dim EncPwd As String = Password
                    '輸入的 Password 是否是明碼需再加密?
                    If NeedEncPwd Then
                        If goaCrypt.EncryptString(Password, EncPwd) = False Then
                            Throw New Exception("密碼編碼失敗:" & goaCrypt.LastErrMsg)
                        End If
                    End If

                    cmd.Parameters.Add("@UserID", SqlDbType.NVarChar).Value = UserID
                    cmd.Parameters.Add("@UserName", SqlDbType.NVarChar).Value = UserName
                    cmd.Parameters.Add("@Password", SqlDbType.VarChar).Value = EncPwd
                    cmd.Parameters.Add("@CreateDate", SqlDbType.SmallDateTime).Value = Now

                    cmd.CommandText = "Select Count(1) From Users Where UserID = @UserID"
                    intRet = cmd.ExecuteScalar

                    If intRet = 0 Then
                        cmd.CommandText = "Insert Into Users (UserID,UserName,Password,CreateDate) VALUES (@UserID, @UserName, @Password, @CreateDate)"
                    Else
                        cmd.CommandText = "Update [Users] Set [Password] = @Password Where [UserID] = @UserID"
                    End If

                    intRet = cmd.ExecuteNonQuery()

                    AddNewUser = (intRet > 0)

                End Using

               ///

            Catch ex As Exception
                ProcMessage(ex.Message, MsgTtl, True, MsgBoxStyle.Exclamation)
            End Try
        End Function

        但最不久後有需要每天新增更新數萬筆產品資料的情況, 這種作法可能速度上不符合要求,
        現在看到 心冷熱情熄 大的全砍全增方式, Bill 大提示的 SqlBulkCopy 方式, 嗯, 有新的方向可研究看看, 謝謝各位前輩提示, 也謝謝 MichaelTsai10 提問, 托福托福.

    • 已標示為解答 MichaelTsai10 2009年11月24日 上午 09:52
    2009年11月23日 下午 03:28

所有回覆

  • 慢慢來好了, 先看這一篇, 處理兩個DataGridView copy的問題.
    http://www.dotblogs.com.tw/billchung/archive/2009/04/12/7990.aspx

    判斷重複應該沒什麼捷逕, 就只能做苦工比對.
    學而不思則罔, 思而不學則殆.
    如果你一直都看不懂、不想學習看懂、抗拒看懂MSDN Library的話,那你最好放棄想要寫好程式這件事
    如果你自私地不肯回饋與分享,那別人為何要花時間回答你的問題?
    2009年11月23日 上午 10:32
    版主
  • Bill大大:
        二個DataView Copy的問題已經解決,但如何將資料存入資料庫及比對資料等問題尚未解決。如果您有空請指導一下感謝您了。

    2009年11月23日 下午 12:52
  • 如果是覆蓋,我的習慣是針對鍵值直接砍所有相關記錄,再直接新增。

    不過這種設計會讓 SQL Server 交易記錄檔快速增加大小...


    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。
    2009年11月23日 下午 01:00
  • 因為要判斷是否重覆,這一點其實只能做苦工.
    一種像心冷大講的, 針對鍵值直接Delete, 再新增,
    這時如果要新增的資料很多, 可以考慮用 [SqlBulkCopy 類別 ] 從DataTable的執行個體做大量複製
    另外一種就是用[SqlDataReader 類別 ]或[SqlCommand. ExecuteScalar 方法 ]
    針對目標資料庫Select 看看有沒有重覆的資料, 如沒有則Insert, 如有則Update
    也許其它前輩會有更好的解法.


    學而不思則罔, 思而不學則殆.
    如果你一直都看不懂、不想學習看懂、抗拒看懂MSDN Library的話,那你最好放棄想要寫好程式這件事
    如果你自私地不肯回饋與分享,那別人為何要花時間回答你的問題?
    • 已標示為解答 MichaelTsai10 2009年11月24日 上午 09:52
    2009年11月23日 下午 01:16
    版主
  • Bill大大:
        可否請妳用比較具體的寫法寫一下,DataGridview存入資料庫的方法,看了你的提示後但卻不知該如何下手寫,所以麻煩你撥空一下針對我的DataGridview變動後新增欄位回寫資料庫做一個較具體一點的說明(程式碼).感謝您。
    如果那位大大有空請指教一下。感謝您。
    2009年11月23日 下午 01:30
  • [.NET Framework 開發人員手冊 ADO.NET 概觀 ]
    這裡有很豐富關於使用ADO.NET的說明, 也有範例程式, 你可以研究研究
    學而不思則罔, 思而不學則殆.
    如果你一直都看不懂、不想學習看懂、抗拒看懂MSDN Library的話,那你最好放棄想要寫好程式這件事
    如果你自私地不肯回饋與分享,那別人為何要花時間回答你的問題?
    2009年11月23日 下午 01:54
    版主
  • Google了一下
    似乎在2006年時就有類似的問題
    你可先參考這篇的作法

    請問dataGridView中的資料要寫回資料庫的問題

    http://social.msdn.microsoft.com/Forums/zh-TW/232/thread/3289dc78-6301-4450-82e3-7c6025889813
    2009年11月23日 下午 02:37

  •     向來我都採用 Bill 大說的第二種方法, 例如:

        Public Function AddNewUser(ByVal UserID As String, ByVal Password As String, ByVal NeedEncPwd As Boolean, _
                                ByVal UserName As String) As Boolean

            If goDB.Open = False Then Exit Function '確認資料庫連線

            Dim MsgTtl As String = "新增使用者"
            Dim intRet As Integer

            Try

               ///

                Using cmd As SqlClient.SqlCommand = goDB.Conn.CreateCommand
                    Dim EncPwd As String = Password
                    '輸入的 Password 是否是明碼需再加密?
                    If NeedEncPwd Then
                        If goaCrypt.EncryptString(Password, EncPwd) = False Then
                            Throw New Exception("密碼編碼失敗:" & goaCrypt.LastErrMsg)
                        End If
                    End If

                    cmd.Parameters.Add("@UserID", SqlDbType.NVarChar).Value = UserID
                    cmd.Parameters.Add("@UserName", SqlDbType.NVarChar).Value = UserName
                    cmd.Parameters.Add("@Password", SqlDbType.VarChar).Value = EncPwd
                    cmd.Parameters.Add("@CreateDate", SqlDbType.SmallDateTime).Value = Now

                    cmd.CommandText = "Select Count(1) From Users Where UserID = @UserID"
                    intRet = cmd.ExecuteScalar

                    If intRet = 0 Then
                        cmd.CommandText = "Insert Into Users (UserID,UserName,Password,CreateDate) VALUES (@UserID, @UserName, @Password, @CreateDate)"
                    Else
                        cmd.CommandText = "Update [Users] Set [Password] = @Password Where [UserID] = @UserID"
                    End If

                    intRet = cmd.ExecuteNonQuery()

                    AddNewUser = (intRet > 0)

                End Using

               ///

            Catch ex As Exception
                ProcMessage(ex.Message, MsgTtl, True, MsgBoxStyle.Exclamation)
            End Try
        End Function

        但最不久後有需要每天新增更新數萬筆產品資料的情況, 這種作法可能速度上不符合要求,
        現在看到 心冷熱情熄 大的全砍全增方式, Bill 大提示的 SqlBulkCopy 方式, 嗯, 有新的方向可研究看看, 謝謝各位前輩提示, 也謝謝 MichaelTsai10 提問, 托福托福.

    • 已標示為解答 MichaelTsai10 2009年11月24日 上午 09:52
    2009年11月23日 下午 03:28
  • 尋找資料庫裡面有沒有的,成本比刪除大,所以資料完全覆蓋時,不問有沒有,直接刪除是比較好的選擇。

    1 筆資料差不太多,10 筆通常 DELETE 一行解決,而 SELECT 卻要查 10 次~

    更多筆時,通常不會是人為輸入,所以要刪除的範圍本身就是從另一個來源刪除,就可以用子查詢做為刪除條件,在 SQL Server 一次就完成,根本不用使用者辛苦作業,但是先查詢有沒有,除了查詢成本,還要增加大量的網路傳輸成本 (假設 SQL Server 不在本機),程式碼還要判斷是新增還是更新,效能差就會很大。


    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。
    2009年11月23日 下午 04:47
  • 親愛的大大們:
         
         試了老半天還是無法將Datagridview3的Record插入到SQl Server,可否幫個忙針對本人問題將Datagridview3的資料插入到資料庫中.

    感謝各位大大
    2009年11月24日 上午 05:53
  • 不了解你的問題。
    你上面看起來會下 SELECT ,難道你不會下 INSERT 嗎?


    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。
    2009年11月24日 上午 07:40
  • 感謝各位大大  後來我用SqlBulkCopy處理 謝謝各位大大
    2009年11月24日 上午 09:51