我正在开发一个具有简单数据库的应用程序。所有功能都进展顺利,但当用户从程序中编辑数据库时,其他用户无法立即看到内容。另一个用户需要关闭程序并重新打开它以显示数据,并使用其他计算机上的更改更新其DBGrid
。我正在使用Delphi 7和ZeosLib来访问我的Firebird数据库。我尝试使用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
答案 0 :(得分:3)
听起来你正在与ACID发生冲突。这是SQL样式数据库的基本保证,所有数据库更新都将是Atomic,Consistent,Isolated和Durable,并通过事务完成。
具体来说,您在使用Consistency和Isolation方面遇到了问题,这确保了外部查看器在完成之前永远不会看到更新,即使该更新包含多个更改也是如此。 (典型的例子是银行转帐,它要求从一个帐户中减去钱并将其添加到另一个帐户。如果您只看到这两个操作中的一个而不是另一个,则表示您的数据不正确。)
您可以将事务视为数据库状态的独立视图。每个数据库连接都有自己的事务,并且它所做的任何更改对其他任何人(隔离)都是不可见的,直到它们提交(完成)事务。根据事务的隔离设置,如果他们有持续的事务,他们可能对其他用户保持不可见,直到他们提交他们的事务并开始新事务。听起来你的代码没有考虑到这一点。
如果您需要立即显示更新,则需要确保transaction's isolation mode为READ COMMITTED
,set 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;