【问题标题】:Update local database all modified data to server database将本地数据库所有修改的数据更新到服务器数据库
【发布时间】:2015-12-30 03:52:24
【问题描述】:

当我想将数据从本地数据库更新到服务器数据时,我遇到了一个问题,替换了本地数据库中已修改的所有内容。我知道这可能很简单,但我对此一无所知,因此将不胜感激。

在我的情况下,我想使用一个按钮将所有修改后的数据上传到 服务器数据库。现在我只是在同一台服务器上使用 2 个数据库来做 测试。

Private Sub btnUp_Click(sender As System.Object, e As System.EventArgs) Handles btnUp.Click
    localconn.ConnectionString = lctext
    serverconn.ConnectionString = sctext
    Try
        localconn.Open()
        serverconn.Open()
        Dim localcmd As New OdbcCommand("select a.acc_id as localid, a.acc_brcid, a.smartcardid, a.acc_created, a.acc_modified as localmodified, b.acd_firstname, b.acd_ic, b.acd_oldic, b.acd_race, b.acd_dob, b.acd_rescity, b.acd_resaddr1, b.acd_telmobile, b.acd_email, b.acd_telwork, b.acd_modified, b.acd_accid from nsk_account a inner join nsk_accountdetail b on a.acc_id = b.acd_accid", localconn)

        Dim servercmd As New OdbcCommand("select c.acc_id, c.acc_brcid, a.smartcardid, c.acc_created, c.acc_modified, d.acd_firstname, d.acd_ic, d.acd_oldic, d.acd_race, d.acd_dob, d.acd_rescity, d.acd_resaddr1, d.acd_telmobile, d.acd_email, d.acd_telwork, d.acd_modified, d.acd_accid from nsk_account c inner join nsk_accountdetail d on c.acc_id = d.acd_accid", serverconn)

        localcmd.CommandType = CommandType.Text
        Dim rdr As OdbcDataReader = localcmd.ExecuteReader()
        Dim thedatatable As DataTable = rdr.GetSchemaTable()

        'localcmd.Parameters.Add("@localid", OdbcType.Int, "a.acc_id")
        'localcmd.Parameters.Add("@localmodified", OdbcType.DateTime, "b.acd_modified")
        Dim localid As String
        Dim localmodi As String
        localcmd.Parameters.AddWithValue("localid", localid)
        localcmd.Parameters.AddWithValue("localmodified", localmodi)

        For Each localid In thedatatable.Rows
            Dim calldata As New OdbcCommand("SELECT acc_modified from nsk_account where acc_id ='" + localid + "'", serverconn)
            Dim reader As OdbcDataReader = calldata.ExecuteReader
            txtSDate.Text = reader("acc_modified").ToString
            If localmodi <= txtSDate.Text Then
                'do nothing, proceed to next data
            Else
                Dim ACCoverwrite As New OdbcCommand("Update nsk_account SET smartcardid = @mykad, acc_created = @created, acc_modified = @modify WHERE acc_id ='" + localid + "'", serverconn)
                Dim DEToverwrite As New OdbcCommand("Update nsk_accountdetail SET acd_firstname = @name, acd_ic = @newic, acd_oldic = @oldic, acd_race = @race, acd_dob = @dob, acd_rescity = @city, acd_resaddr1 = @address, acd_telmobile = @phone, acd_email = @email, acd_telwork = @language, acd_modified = @detmodify WHERE acd_accid ='" + localid + "'", serverconn)
                ACCoverwrite.ExecuteNonQuery()
                DEToverwrite.ExecuteNonQuery()
            End If
        Next

        MessageBox.Show("Upload success", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning)

    Catch ex As Exception
        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning)
    Finally
        localconn.Close()
        serverconn.Close()
    End Try
End Sub

任何意见或建议将不胜感激。

【问题讨论】:

    标签: mysql vb.net winforms


    【解决方案1】:

    我希望你的意思是一桌一桌。我没有阅读您的代码,但您明白了 - 您需要 2 个连接,但这里有 2 种不同的方法。

    方式#1 - 您可以在大量数据时使用(怎么说更好? - 不是很大)。您可以使用来自服务器的数据加载 DataTable 对象并更新更改的记录。您可以使用DataAdapter 并发出CommitChanges - 所有更改/新行都将写入服务器。

    注意:您需要一种机制,能够可靠地判断哪些行是本地数据库上的新行和已修改行。如果您在本地数据库中的 PK 与服务器上的不同,您可以吗?你需要回答这些问题。可能你需要一个特殊的本地PK机制。例如,使用负 PK 整数添加行,这将告诉您这些行是新的。并使用“ModifiedDate”,它与 PK 一起判断该行是否需要更新。

    方式 #2 - 随时使用,即使数据量较大。取一个本地行并检查它。如果它是新的 - insert,如果它是现有的并且“DateModified”已更改 - 执行 update。如何做到这一点有很多变化。可以使用SQLMERGE语句等。

    但这是两种主要方式 - 直接行插入/更新和断开连接更新/批量提交。

    此外,您可以使用事务批量执行 - 更新一些行提交,然后开始新事务。如果您在更新应用程序时正在使用它,这将有所帮助。

    我希望这些想法有所帮助。如果你做你所做的,你在哪里

    For Each localid In thedatatable.Rows
    

    我不确定localid 是什么。应该是

    ' prepare command before loop
    sql = "Select * From Table where ID = @1"
    ' you will create parameter for @1 with value coming from 
    ' row("ID")
    Dim cmd As New .....
    cmd.Parameters.Add(. . . . )
    For Each row As DataRow In thedatatable.Rows
    
        cmd.Parameters(0).Value = row("ID") ' prepare command upfront and only change the value
        using reader as IDataReader = cmd.ExecuteReader(. .  . . )
            If Not reader.Read() Then 
                ' This row is not found in DB - do appropriate action
                Continue For
            Else
                ' here check if the date matches and issue update
                ' Better yet - fill some object 
            End if
        end using
    
        ' if you fill object with data from your row -here you can verify if
        ' update needed and issue it  
         . .  . . . . 
    
    Next
    

    【讨论】:

    • 更具体地说,它是表到表(例如,用户名到用户名,密码到密码)我通过使用 2 个连接来理解,但我以前从未尝试过,所以我被困在 For Each 进程读取所有主键以更新我的数据
    • @TheButterfly 我认为打开 2、4、8 个连接没有问题。我在您的应用程序中看到的问题是,您将为每个表重复此代码,并且通常代码太多。避免这种情况的方法之一是使用DataAdapterCommandBuilder。你给选择它准备更新/删除/插入,或者你可以为适配器准备自定义命令。基于架构。但是你无法避免的一件事——编写逻辑,你如何确定要更新什么。您是否将本地行标记为已删除?您可能需要一些唯一的业务密钥来识别行。这不仅仅是 For 循环。
    • 在我看来,上传的流程是 1.) 比较修改日期,如果本地数据库有更新的修改日期,则继续更新 2.) 数据将保留在本地数据库中而不会删除。全部基于修改日期
    • 仅供参考,本系统是将个人信息注册到会员卡中,因为新记录实际上会先存储到服务器并下载到本地,因此本地只需要处理更新,因为所有ID都匹配服务器
    • @TheButterfly 你的问题是什么。您有 ID 和 Mod 日期(如果您有另一个实际上已更新的本地标记,那会更容易)没有标记 - 对于每个 - 从服务器中选择(加载数据表(1 条记录)) - 检查日期。如果不匹配 - 更新该单行,发出提交更改,清除表,下一行....
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多