当多个用户正在编辑TDBGrid时,TDBGrid不会更新

时间:2013-05-01 18:22:45

标签: delphi delphi-7 firebird dbgrid zeos

我正在开发一个具有简单数据库的应用程序。所有功能都进展顺利,但当用户从程序中编辑数据库时,其他用户无法立即看到内容。另一个用户需要关闭程序并重新打开它以显示数据,并使用其他计算机上的更改更新其DBGrid。我正在使用Delphi 7和ZeosLib来访问我的Firebird数据库。我尝试使用DBNavigator上的刷新按钮,但它不起作用。

我用来连接数据库的组件是:

  • Z型连接
  • ZQuery
  • 数据源
  • 的DBGrid
  • 的DBNavigator

这是我的ZConnection和ZQuery的代码。

object ZConnection1: TZConnection
    ControlsCodePage = cGET_ACP
    UTF8StringsAsWideField = False
    Connected = True
    Port = 3051
    Database = '192.168.254.254:test'
    User = 'test'
    Password = 'test'
    Protocol = 'firebird-2.5'
    Left = 96
    Top = 8
  end
  object ZQuery1: TZQuery
    Connection = ZConnection1
    Active = True
    SQL.Strings = (
      'select * from "test"')
    Params = <>
    Left = 128
    Top = 8
      object ZQuery1ID: TStringField
      FieldName = 'ID'
      Required = True
      Size = 8
    end

4 个答案:

答案 0 :(得分:3)

听起来你正在与ACID发生冲突。这是SQL样式数据库的基本保证,所有数据库更新都将是Atomic,Consistent,Isolated和Durable,并通过事务完成。

具体来说,您在使用Consistency和Isolation方面遇到了问题,这确保了外部查看器在完成之前永远不会看到更新,即使该更新包含多个更改也是如此。 (典型的例子是银行转帐,它要求从一个帐户中减去钱并将其添加到另一个帐户。如果您只看到这两个操作中的一个而不是另一个,则表示您的数据不正确。)

您可以将事务视为数据库状态的独立视图。每个数据库连接都有自己的事务,并且它所做的任何更改对其他任何人(隔离)都是不可见的,直到它们提交(完成)事务。根据事务的隔离设置,如果他们有持续的事务,他们可能对其他用户保持不可见,直到他们提交他们的事务并开始新事务。听起来你的代码没有考虑到这一点。

如果您需要立即显示更新,则需要确保transaction's isolation modeREAD COMMITTEDset up database events以便在更新各种内容时向已连接的客户端发送通知,这样客户端就可以刷新他们的数据。您还需要确保用户更新立即导致提交操作,以便隔离的数据可用。

由于我不使用ZeosLib,我无法解释您需要如何设置这一切的所有细节,但这足以让您走上正确的轨道。

答案 1 :(得分:0)

我建议您在显示网格的表单中添加一个计时器。设置计时器,使其每分钟(或更长时间)触发一次OnTimer事件。在这种情况下,关闭查询然后重新打开它。通过这种方式,每个人都可以获得最新信息(尽管已经很晚了)。

with qWhatever do   // this is the query which is connected to the grid
 try
  disablecontrols;
  close;
  open
 finally
  enablecontrols
 end; 

答案 2 :(得分:0)

对于客户端需要接收通知的多用户应用程序,一种选择是使用 Firebird events 为每次数据更改发送“广播”消息(SQL INSERT,UPDATE或删除)。

客户端可以“注册”(监听)特定的消息类型,每当Firebird服务器发送具有此类型的消息时,他们都会收到它,并运行客户端应用程序代码,在您的情况下将刷新用户界面(网格)。

虽然在许多简单的用例中这可以是一个充分的解决方案,但也存在一些限制。我最近在这里写了关于这个主题的博客:

(我是Delphi和Free Pascal中间件库的作者)

答案 3 :(得分:0)

我在查询之前添加了这个问题解决了这个问题。

IBDatabase1.Close;

IBDatabase1.Open;