【问题标题】:Using DataTables to merge databases使用 DataTables 合并数据库
【发布时间】:2012-12-03 11:03:38
【问题描述】:

我有以下代码应该用远程用户表覆盖本地用户表。我可以看到 Merge 工作正常,但 Update 什么都不做(即 DataTable 有新值,但它没有将它写入 LocalDb 连接/数据库) - 有没有一种简单的方法来做我正在做的事情或完成这项工作?

var RemoteUsersTable = DbRemote.ExecuteQuery("SELECT * FROM users");

if (RemoteUsersTable.Rows.Count > 0)
{
    SqlDataAdapter LocalDataAdapter = null;
    var LocalUsersTable = DbLocal.ExecuteQuery("SELECT * FROM users", ref LocalDataAdapter);

    LocalUsersTable.Merge(RemoteUsersTable);
    LocalUsersTable.AcceptChanges();

    LocalDataAdapter.Update(LocalUsersTable);
}

【问题讨论】:

    标签: c# .net sql datatable


    【解决方案1】:

    对 AcceptChanges 的调用意味着 LocalUsersTable 中任何已更改的值都不再标记为已更改,因此无需更新任何内容。

    无论如何,这是执行大规模更新的一种非常丑陋、缓慢且危险的方式,并且从未使用过。只是一些最严重的问题:

    • 您将所有数据从两台服务器拉到客户端,然后再将所有数据发送回其中一台服务器。这会浪费所有机器的带宽和处理时间,因此速度非常慢。
    • 您从每个表中检索所有列,如果有架构更改,这将导致更新失败。

    您应该在事务中使用 SQL 语句来做您想做的事情,而不是使用 DataTables。

    SQL Server 具有 MERGE 语句,该语句可以使用源查询中的行更新目标表,并使用每个单独行的值决定要执行的操作(更新、插入、删除)。或者您可以编写一个多语句脚本,删除旧行并在事务中插入新行

    【讨论】:

    • AcceptChanges 调用没有区别。我可以跨多个连接使用单个事务吗?如果是这样,非常感谢一个链接/示例(这是我最初想做的)。
    【解决方案2】:

    上述代码的问题在于您只设置了一个选择命令。如果您想要“更新”表格,那么您很可能需要为您的LocaDataAdapter 提供“更新”和“插入”命令。

    DataAdapter 的Update 方法需要这些命令来更改/添加/删除数据库表中的记录。

    您通常会使用特定命令设置 DataAdapter。

    使用您的命令生成器,您可以尝试这样做:-

    var RemoteUsersTable = DbRemote.ExecuteQuery("SELECT * FROM users");
    
    if (RemoteUsersTable.Rows.Count > 0)
    {
        SqlDataAdapter LocalDataAdapter = null;
        var LocalUsersTable = DbLocal.ExecuteQuery("SELECT * FROM users", ref LocalDataAdapter);
    
        LocalUsersTable.Merge(RemoteUsersTable);
        LocalUsersTable.AcceptChanges();
    
        cb.GetDeleteCommand(); // WHICH EVER YOUR COMMANDBUILDER IS CALLED.
        cb.GetInsertCommand();
        cb.GetUpdateCommand();
    
        LocalDataAdapter.Update(LocalUsersTable);
    }
    

    【讨论】:

    • 我没有包含 DbLocal 类背后的代码,它是这样做的:SqlCommandBuilder CommandBuilder = new SqlCommandBuilder(refDataAdapter); refDataAdapter.Fill(table); 我认为命令生成器为我做这件事是正确的,对吧?
    • 不,DataAdapter 需要三个命令。带参数的插入命令和带参数的更新命令。以及用于抓取数据的 Select 命令。
    • RefDataAdapter.Fill(table),正在使用 select 命令,但您没有告诉您的 DataAdapter 它是如何插入、更新或删除的。
    • This MSDN page 声明“如果您设置 SqlDataAdapter 的 SelectCommand 属性,您可以创建一个 SqlCommandBuilder 对象来自动生成单表更新的 Transact-SQL 语句。然后,任何附加的 Transact-SQL 语句你不设置是由 SqlCommandBuilder 生成的。” ...所以我认为您说对了一半-它只能更新,不能插入。你怎么看?
    • 查看我的编辑。我认为您缺少上述部分。我通常不使用命令生成器,我手动完成所有这些操作。
    猜你喜欢
    • 2016-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-08
    • 1970-01-01
    • 1970-01-01
    • 2016-10-05
    • 2010-09-15
    相关资源
    最近更新 更多