【问题标题】:Detect If Current Record is Deleted on Access Bound Form检测当前记录是否在访问绑定表单上被删除
【发布时间】:2016-04-12 17:28:02
【问题描述】:

如果用户 #1 删除了我们的 Access 2007 数据库(SQL Server ODBC 链接表)中的一条记录,其他用户可能会在该记录中显示 #Deleted#(在数据表视图表单上)。在某些情况下,这可能会导致问题,因为我的代码在表单的当前事件上运行,并且只是假设存在有效记录(或新记录)。

有没有可靠的方法来检测当前记录是否已被删除?我想将它包装在这样的函数中:

Public Function IsRecordDeleted(ByRef r As DAO.Recordset)
   'what goes here?
End Function

我确实在 MSDN 的 DAO 参考中找到了 RecordStatus 属性,但该属性似乎仅在 RecordSet 配置为批量更新时才有效。当我尝试检查它的值时,我得到:运行时错误 3251 - 这种类型的对象不支持操作。

我实际上在一两年前就同样的问题在另一个论坛上发布过。给出的建议不起作用:

  • DCount()
  • 记录集的书签和 NoMatch
  • 检查 PK 或 FK 字段中的#Deleted

【问题讨论】:

  • 好问题,但我认为在当前事件中重新查询不起作用。这将导致无限循环。但是,如果我确实检测到一条已删除的记录,那么我确实必须重新查询才能解决我猜想的问题。
  • @HK1 这可能没有严格的帮助,但我总是建议在使用 db 服务器作为后端时避免使用 DAO 链接的绑定表单。使用 ADO 在服务器端而不是本地运行任何查询,并为表单编写未绑定的解决方案。
  • 感谢马特的推荐。我倾向于使用 ADO 作为最后的手段。如果 DAO 和 ODBC 做我需要的事情,我想我认为不需要改变。但我意识到 ADO 通常被认为更稳定、更健壮。

标签: ms-access vba


【解决方案1】:

对我来说,这看起来更像是一般的应用程序设计疏忽,而不是具有简单解决方法的简单问题。

如果您对重要位置的记录可用性做出假设,那么您必须将删除记录的可能性考虑为您数据的主要(和有效)状态。

有可能——但我认为不太可能——你会找到一种解决方法,但我认为你应该仔细看看你的整体设计本身。

一些解决问题的方法,对您的情况可能有用也可能没用,具体取决于用户包含和访问您的数据的方式:

  • 如果您不能确定记录是否存在,请不要依赖记录的存在。
    基本上,修改你的假设并修改你现有的代码,以避免依赖于强制存在的记录。

  • 职责分离
    不允许不同用户对相同数据拥有相同的创建/编辑/删除权限。例如,采购订单应该属于创建它的用户。不允许其他用户单独删除该订单或其商品。

  • 实际上不要删除实体,只允许用户将其标记为“已取消”或“已过时”并出于历史原因将其保留在数据库中(或稍后清除它们)。

  • 或者,实际上不要删除记录,而是添加一个隐藏的布尔字段以在用户想要删除它们时将它们标记为“已删除”。然后你可以做一些清理工作,比如每晚,然后实际删除标记的记录。
    当然,您必须从查询和表单等中排除这些“已删除”的记录,但数据完整性将得到保留。

  • 将报告和记录列表设为只读,这样用户就不能随便在任何地方删除它们。例如,如果用户可以查看采购订单项目,则不允许他们删除该数据,除非他们实际打开采购订单详细信息表单。

  • 在本地缓存记录,以便如果它们从后端数据库中消失,它们仍会显示给查看它们的用户,直到他们刷新列表。
    这对于只读报告通常很有用:将查询结果加载到本地表中并绑定该表,而不是使用实时数据进行查询。
    正在查看的数据可能有点陈旧,因为它不会实时更新(因为它是在本地缓存的),但对于报告,通常没问题(只需在表单上提供“刷新”按钮以允许用户强制刷新) .

  • 尝试各种锁定选项(请参阅database optionsform record locking),以在其他人访问记录时禁止删除记录。

  • 管理您自己的锁定方案。
    作为最后的手段,您可以在“LockingStatus”表中记录当前正在被其他人查看或编辑的 ID 和记录。例如:

    Table: LockStatus
    Field: LockNature:   Whether the record is being Edited or Viewed
    Field: LockedTable:  Name of the table of the record being locked
    Field: LockedRecord: ID of the record being locked
    Field: User:         Name of the user holding the lock
    Field: LockTime:     DateTime of the lock creation, so you can detect 
                         and remove stale locks
    

    当用户查看或编辑记录时,首先检查表中是否存在该记录的现有条目。如果有,则告诉用户他们无法执行该操作,因为其他人正在查看数据。如果没有现有条目,请添加一个,允许编辑,并在编辑完成后删除记录。
    这充满了复杂性,因为您需要跟踪用户何时移动到另一条记录,以便您可以解锁前一条记录,如果您不小心,您最终可能会遇到很多过时的锁,但之前已经完成.

  • 如果您仍然真的想规避删除记录问题,请查看在您的 VBA 代码中,当您从其他位置删除记录时出现错误 3167“记录已删除”的位置。
    一旦您知道它在代码中出现的位置,使用On Error 3167 Goto YourErrHandler 捕获该错误以优雅地处理该特定错误(这实际上取决于您的表单的设计方式以及您如何使用数据)。

  • 另一种选择是使用全局错误处理程序进行访问。
    我只知道vbWatchdog。它不是免费的,但效果非常好,并且很容易集成到应用程序中。
    此加载项集成在您的应用程序中,无需为每个用户单独安装。设置完成后,您的应用程序将能够在高级别捕获所有错误。因此,您将能够捕获“记录已删除”错误并在一处处理它们。

【讨论】:

  • 感谢您提供完整的解决方案和想法列表。我不确定我是否 100% 同意您所写的所有内容,但我认为您的回答可以很好地解决问题。
【解决方案2】:

我通过 Form_Current 事件中的代码遇到了同样的事情,并在这里结束。

错误处理是最好的(也是唯一的?)方法。出于我自己的目的,我只是在当前事件中运行了一些简单的控件更新,所以我编写了错误处理程序来从我遇到的错误中恢复

Private Sub Form_Current()
    On Error GoTo handler

    'do intended things here, e.g. attempt to access the value
    'of a control even though the record may be deleted  

    Exit Sub

  handler:
    If Err.Number = 438 Or Err.Number = 13 Then 
        'type mismatch, probably due to deleted record, skip it
        Resume Next
    ElseIf Err.Number = 3167 Then 
        'record is deleted, skip it
        Resume Next
    Else
        Err.Raise Err.Number, Err.Source, Err.Description
    End If
End Sub

我没有可靠地得到 3167(记录已删除),但是在尝试访问值属性时,我似乎只得到了上面捕获的 3 个错误。

如果您当前的事件较长,或者运行这样的代码有风险,您可以使用类似的技术,但故意在方法开头引发错误(dummyvalue = SomeBoundControl.Value 应该可以解决问题)然后将错误处理程序中的“Resume Next”更改为“Exit Sub”。

【讨论】:

    【解决方案3】:

    如果记录仍然存在,您可以检查确定不是空白的字段

    第一次打开表单时,我使用默认值 =Now() 自动填充的更新日期或创建日期字段。

    因为如果记录被删除,它的值似乎会变成一个空字符串,我可以触发

    If Me.DateUpdated = "" Then
    

    在表单本身上(例如,在关闭过程中跳过操作)。此检查也可能适用于其他形式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多