因此,Access中的记录锁定非常糟糕。我不能使用内置记录锁定,因为它锁定记录的“页面”而不是单个记录(我已经尝试更改设置以使用记录级锁定,但它仍然锁定页面而不是仅仅一条记录),但即使我可以解决这个问题,它也无法解决我的问题,因为在用户开始在表单中进行更改之前,记录不会锁定。
问题是,当两个人打开相同的记录时,他们可以开始进行更改并保存(从而覆盖之前的更改)。更糟糕的是,表单上有列表框链接到其他表(键入ID),然后他们对这些表所做的更改会被后面的任何更改覆盖,如果它们都打开了相同的记录。
长话短说,我需要确保两个人不可能同时打开相同的记录(无论他们是否对其进行了任何编辑)
为此,我在表格中添加了一个字段,表示某个记录是否已被用户锁定。当他们打开表单时,它会在字段中设置他们的名字,而尝试打开该记录的其他用户会收到一个已经锁定的通知。问题是,这种“锁定”不是即时的。其他用户需要几秒钟“检测”记录被锁定,因此如果两个人在大致相同的时间尝试打开相同的记录,它将允许他们打开它。我已经将一个事务应用于设置锁定的UPDATE语句,但它仍然留下一个短窗口,其中锁定没有“占用”,两个人可以打开相同的记录。
那么,有没有办法立即进行UPDATE(所以所有其他用户立即看到其结果),或者更好的是,一种在Access多用户环境中锁定记录的强大而全面的方法?
答案 0 :(得分:3)
不清楚为什么你只接受“页面”锁定。
如果在file->选项中启用行锁定,则还需要设置特定表单以锁定当前记录。所以只是打开记录锁定对你没有帮助。该设置仅设置新表单的默认设置 - 它不是系统范围的设置。
如果您正确打开表单的锁定,那么如果两个用户正在查看同一记录并且一个用户开始编辑该记录,则所有其他用户都无法编辑该记录。尝试编辑记录的任何其他用户都会在记录选择器栏中看到“锁定”图标(假设为给定表单打开了选定的记录)。他们还会收到一声“哔”声。如果他们试图在给定表格上输入任何可编辑的控件。
当他们尝试编辑时,他们会看到一个可见的"锁定"选择器栏上的图标如下:
一些事情:
如果两个用户能够编辑记录,那么您不能为该给定表单启用锁定。必须在表格的基础上设置此功能。更改file-> options->客户端设置中的设置仅为您创建的新表单设置默认值!因此,设置仅适用于新表单的默认设置 - 它不会更改现有表单。
因此,设置记录锁定只是表单设置的一种形式。
因此,您始终必须将要锁定的每个表单设置为当前编辑的记录。您可以在表单设计中,在属性表的数据选项卡中设置它,如下所示:
并且还要记住,记录级别锁定(不同的设置和功能)的设置是访问客户端设置,不会随给定的应用程序一起移动。
因此,既然您声明两个用户可以编辑同一个记录,那么CLEARY您永远不会为该给定表单启用记录锁定。系统范围的“默认”记录锁定仅将上面的表单设置为默认值(因此您的现有表单不会更改)。
接下来: 使用记录级锁定设置[x]打开数据库是Access客户端设置,不与应用程序一起保存。因此,这是一个访问范围设置,不是应用程序设置,也不是与应用程序一起运行的设置。
所以你必须在每个客户端工作站上设置它,或者你必须在你的启动代码中设置它。
如果您无法绕过并更改每个工作站以更改此设置(或使用访问运行时),则可以在启动代码中使用此VBA来设置此功能:
Application.SetOption "Use Row Level Locking", True
请注意,该设置在退出应用程序之前不会生效,但这确实是一个“非”问题,因为这意味着第一次运行此代码时,某些用户可能处于页锁定模式,而其他用户则处于行锁定状态模式。大多数情况下,这几乎没有问题。
但是,下次任何用户启动应用程序时,它们将处于行锁定模式。
我过去也写过自定义锁定代码。并且可以概述如何使这项工作做得很好,但是从你到目前为止发布的内容来看,你从来没有开启或设置锁定,也没有为你现在拥有的任何形式正确锁定。答案 1 :(得分:1)
答案 2 :(得分:1)
好的,我终于找到了所有有助于此的问题并制定了解决方案。
问题是多方面的,所以我将单独讨论这些问题:
第一期:我的自定义锁定不是即时的。即使我使用了一个事务,但在锁定之后几秒钟,用户仍然可以同时访问同一条记录。我正在使用CurrentDb.Execute来更新事务的记录和工作空间(0).BeginTrans。出于某种原因(尽管微软从这里得到了相反的保证:https://msdn.microsoft.com/en-us/library/office/ff197654.aspx),问题在于使用Workspaces对象时交易不起作用。当我切换到DBEngine.BeginTrans时,锁定是即时的并解决了我的直接问题。
具有讽刺意味的是,我几乎总是使用DBEngine进行交易,但这次没有理由使用Workspaces,所以这显然是一个不好的举动。
第二个问题:我首先必须使用自定义锁定的原因是因为记录级锁定没有按预期工作(尽管配置正确)。它仍在使用页面级锁定。这是由于我在这里使用的表现技巧:https://msdn.microsoft.com/en-us/library/dd942824%28v=office.12%29.aspx?f=255&MSPPError=-2147217396
技巧涉及打开与包含链接表的数据库的连接,从而加快链接表操作。问题是OpenDatabase方法与记录级锁定不兼容,因此它使用页面级锁定打开数据库,并且由于第一个打开数据库的用户确定其锁定级别(如下所述:https://msdn.microsoft.com/en-us/library/aa189633(v=office.10).aspx) ,所有后续连接都被强制为页面级别。
第三个问题:我的问题是我的表单不仅仅是单个表的简单绑定表单。他们打开一个记录(不允许用户导航)并提供几个功能,允许用户进行修改,影响其他表中与他们正在编辑的记录相关的其他记录(通过组合框和弹出窗体什么不是。因此,我不能允许两个人同时打开相同的记录,因为它留下了太多的机会让用户走过彼此。变化。因此,即使我删除了OpenDatabase性能技巧,我仍然必须在打开它时立即强制使用Form,这样记录就会立即锁定,而其他任何人都无法打开它。我不知道这是否会像我的自定义锁定那样瞬间完成,而且还没有测试过那个方面。
无论如何,我需要在用户打开它的时刻锁定一条记录,现在我决定继续使用我的自定义锁定(使用该事务的修复程序)。如果发现其他不太理想的东西,我可以尝试删除OpenDatabase技巧并切换到Access的内置锁定,并在每个记录打开时强制立即锁定。
答案 3 :(得分:0)
由于Access不能使锁定记录变得容易,所以我想知道您是否要添加带有锁定记录条目的表,即使它是“胶带,汤罐和衣架”,是否也可以解决问题?解决方案:您创建一个具有2个字段的“ Locked_Record”表,a)正在更新记录ID,b)更新该记录的人员的用户名。该表将精确地控制谁拥有,因此可以编辑什么记录。您的表单将具有一个搜索字段,当输入搜索词并按“ Enter”键时,表单将通过在数据中查找并在Locked_Record表中查找来搜索记录。如果在Locked_Record表中找到,则用户会收到一条错误消息,提示“记录已在使用中”,并显示记录的所有者。如果在数据中找不到,则会显示相应的消息。如果在数据中找到但在Locked_Record表中找不到,则将创建一个Locked_Record条目,然后用户将获得表格中显示的数据。此时,没有其他人可以编辑该记录。当用户完成更新时,用户要么需要按下“完成更新”按钮,要么必须关闭表单。无论哪种方式,都会删除Locked_Record条目,以便其他人可以使用该记录。如果记录所有者没有关闭表格或不按按钮,那么这就是培训问题。该方法可以是多个实体(例如客户,员工,部门等)的用户。您只需要确保已设置应用程序和数据库,就可以使用任何可能锁定其他表的子表单来仅影响该记录在其他表格。
答案 4 :(得分:0)
我知道这有点旧,但是这里的信息启发了我使用以下内容。基本上,me.txtApplication是绑定表单上的文本框。表单绑定到表,并设置为锁定属性部分中的已编辑记录。除了触发该编辑锁定并立即撤消更改外,此代码不会执行任何其他操作。如果另一个用户尝试加载相同的记录,它将尝试进行相同的编辑,触发错误并移至下一个记录或开始新记录,而无需用户明智。
'Lock current record with edit-level lock by editing and removing the edit from a
field.
'If record is already locked, move to next record.
On Error Resume Next
Me.txtApplication = Me.txtApplication & "-%$^$^$$@#$"
Me.txtApplication = Replace(Me.txtApplication, "-%$^$^$$@#$", "")
If Err.Number = -2147352567 Then
If Me.CurrentRecord < Me.Recordset.RecordCount Then
DoCmd.GoToRecord , , acNext
Else
MsgBox "No available records.", vbOKOnly, "No Records"
DoCmd.GoToRecord , , acNewRec
'[If the condition is not true, then we are on the last record, so don't go
to the next one]
End If
End If
End Sub