使用DataTables合并数据库



我有下面的代码,应该用远程的覆盖本地的Users表。我可以看到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);
}

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

无论如何,这是一种非常丑陋、缓慢且有风险的大规模更新方式,而且从未使用过。只有几个最严重的问题:

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

您应该在事务中使用SQL语句来执行您想要的操作,而不是使用DataTables。

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

上面代码的问题是您只设置了一个select命令。如果你想"更新"表,那么你很可能需要一个"更新"&LocaDataAdapter的"INSERT"命令。

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);
}

最新更新