【问题标题】:Auto refresh a TDataSet / DBGrid自动刷新 TDataSet / DBGrid
【发布时间】:2017-03-09 13:14:46
【问题描述】:

我正在开发一个通过TSimpleDataSet(dbExpress 组件)在DBGrid 中显示信息的软件

有问题的软件由 2 个不同的人在 2 台不同的计算机上使用。

他们都在不同的时间查看和编辑相同的信息。 我正在尝试找出一种方法来自动更新计算机 B 上的 DBGrid(或者更确切地说是 DataSet,对吗?),一旦计算机 A 对一行进行更改(编辑某些东西/什么),反之亦然.

目前我已经设置了一个名为RefreshTButton,一旦点击它就会执行以下代码:

procedure TForm2.actRefreshDataExecute(Sender: TObject);

begin
    dbmodule.somenameDataSet.MergeChangeLog;
    dbmodule.somenameDataSet.ApplyUpdates(-1);
    dbmodule.somenameDataSet.Refresh;
    dbmodule.somename1DataSet.MergeChangeLog;
    dbmodule.somename1DataSet.ApplyUpdates(-1);
    dbmodule.somename1DataSet.Refresh;
    dbmodule.somename2DataSet.MergeChangeLog;
    dbmodule.somename2DataSet.ApplyUpdates(-1);
    dbmodule.somename2DataSet.Refresh;
    dbmodule.somename3DataSet.MergeChangeLog;
    dbmodule.somename3DataSet.ApplyUpdates(-1);
    dbmodule.somename3DataSet.Refresh;
end;

这很好,一旦点击就可以按预期工作。 我想要一个自动更新功能,例如当计算机 A 连续编辑信息时,计算机 B 的 DBGrid 应该相应地更新它的显示,而无需单击刷新按钮。

我想我会使用 TTimer 并在两台 PC 上的两个软件上设置一个特定的时间间隔。

我的实际问题是:

有没有比TTimer 更好的方法呢?如果有,请详细说明。 此外,如果TTimer 路线是获取任何进一步信息的方式,您可能会发现对状态有用的信息将不胜感激(赞成和反对等)

我正在使用 Rad Studio 10 Seattle 和 dbExpress 组件,数据集连接到我的网站所在主机上的 MySQL 数据库。

谢谢!

【问题讨论】:

  • 当然更好的方法是由数据库服务器通知。为此,数据库服务器(如果有的话)需要提供这样的功能,并且访问驱动程序也需要支持它。 DBX 可能不会,但应该可以使用辅助连接。就像 IBEventAlerter 一样,例如 interbase/firebird。
  • 为什么这会比计时器更好?只是出于好奇。另外,我正在使用 MySQL,是的,数据集已连接到数据库
  • 您的程序不需要经常敲击服务器。可能 99% 的刷新都是空手而归。如果您延长间隔以避免这种情况,那么您将承担不通知更改的风险。
  • 按照您的方式进行操作需要重复往返服务器(每次调用 MergeChangeLog,一次调用 ApplyUpdates,一次调用 Refresh),其中绝大多数除了浪费网络带宽和CPU 周期。想象一下在办公室里移动的文件。您的代码相当于沿着大厅跑到同事的办公桌前寻找新工作,回到您的办公桌,然后又立即回到大厅。不是认真去工作的,对吧?使用服务器通知意味着坐在你的办公桌前工作,然后让你的同事在工作到达时给你打电话。
  • @KenWhite 你的例子让我大笑起来,哈哈。所以基本上我可以设置你提到的服务器通知并将其绑定到我的软件,以便它在收到通知时更新(触发计时器/Tbutton?)?希望我做对了。如果是这样,我想这有很多事情要做,而且不适合这个问题,所以你能在评论中提供一些链接,这样我就可以阅读并开始这个问题了吗?谢谢!

标签: delphi dataset refresh dbgrid ttimer


【解决方案1】:

只需使用计时器并使其每 5 分钟刷新一次数据集。没什么大不了。 如果使用不频繁,则可以将其设置为每 10 或 15 分钟触发一次。 如果将计时器设置为更长的间隔,则计时器没有任何问题。 今天的宽带连接可以轻松处理流量,Access 也可以。 当然,如果桌子不是很大。

【讨论】:

    【解决方案2】:

    嗯,Ken White 和 Sertac Akyuz 肯定是正确的,即使用源自服务器的通知来确定何时刷新您的本地数据集比不断地从服务器重新读取您正在使用的所有数据更可取。

    AFAIK 的问题是没有与 MySql 一起使用的 Emba 提供的通知系统。请参阅 FireDAC 的数据库警报支持的数据库列表:

    http://docwiki.embarcadero.com/RADStudio/XE8/en/Database_Alerts_(FireDAC)

    并注意它没有列出 MySql。

    幸运的是,我认为对于像您目前这样的小型系统来说,有一种解决方法应该是可行的。据我了解,您和您同事的 PC 在 LAN 上,而 MySql Server 在您的 LAN 之外和 Internet 上。在这种情况下,你们中的一个人不需要往返服务器就可以收到另一个人更改了数据库中的某些内容的通知。使用类似于 Ken 的类比,您可以俯身在桌子上对您的同事说:“嘿,我改变了一些东西,所以您需要刷新您的数据。”

    一种技术含量非常低的实现方式是在您的 LAN 上的某个地方拥有一个你们双方都可以轻松获取的资源,当您对数据库进行更改时,您可以更新该资源,这意味着你们中的另一个应该从服务器更新您的数据。一种方法是拥有一个包含许多记录的小型共享数据文件,每个服务器数据库表一个,它具有某种时间戳或版本 ID 号,当您更新相应的服务器表时会更新。然后,您可以定期检查(轮询)此数据文件,以查看自上次检查以来给定表是否已更改;显然,如果有,然后您从服务器重新读取您想要的数据,并更新您从共享文件中读取的信息的本地记录。

    您可以使用 Delphi 客户端数据集的事件处理程序更新共享文件。

    这个主题有很多变体,我相信你会很清楚;实现细节真的不重要。

    要更新我所说的共享文件,您需要在写入时锁定它。这个答案:

    How do I get the handle for locking a file in Delphi?

    将向您展示如何做到这一点。

    当然,共享的本地资源不一定是数据文件。一种替代方法是使用 Microsoft 消息队列服务,该服务有时用于此类事情,但学习曲线比共享数据文件更陡峭。

    顺便说一句,如果您使用 3 层数据库访问(例如使用 datasnap),这种事情会容易得多(至少在像您这样的小规模上)。 在三层系统中,只有中间层(您编写的 Delphi datasnap 服务器,但并不难)与服务器通信,客户端只与中间层通信。这使得中间层服务器很容易在其中一个客户端更改数据库数据时通知其他客户端。

    三层安排还有助于最大限度地减少通过 Internet 访问数据库服务器的安全问题,因为您只需要一个与服务器的安全连接,而不是每个客户端一个。但这离您的直接问题有点远。

    我希望这一切都清楚,如果没有,请询​​问。

    【讨论】:

    • 非常有帮助,谢谢,刚刚阅读了大部分内容,很快就会尝试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-28
    • 1970-01-01
    • 2016-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多