2012-05-02 76 views
4

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

是否有任何可靠的方法来检测当前记录是否已被删除?我想它包在像这样的功能:

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

我发现在MSDN中的DAO参考RECORDSTATUS属性,但该属性出现如果记录配置为批量更新仅是有效的。当我尝试检查它的值时:运行时错误3251 - 此类对象不支持操作。

我实际上在一年或两年前在另一个论坛上发布了关于这个同样的问题。给出的建议不工作:

  • DCOUNT()
  • 书签和记录的NOMATCH
  • 在PK或FK场
+0

好问题,但我不认为它会适用于当前事件中的Requery。那会导致无限循环。但是,如果我确实检测到删除的记录,那么我确实需要重新查询才能解决问题。 – HK1

+0

@ HK1这可能不会有什么帮助,但我总是建议使用db服务器作为避免使用DAO链接绑定表单的后端。与ADO一起运行任何查询服务器端而不是本地服务器,并且为表单提供未绑定的解决方案。 –

+0

感谢您的推荐。我倾向于使用ADO作为最后的手段。如果DAO和ODBC做我需要的东西,我想我没有看到需要改变。但是我意识到ADO通常被认为更稳定和更强大。 – HK1

回答

3

对我来说,这看起来更像是检查中#Deleted一个通用的应用程序设计监督,而不是一个简单的解决方法。

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

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

解决这个问题,这可能是也可能不是你的情况是有用的,这取决于你的数据是如何包含与用户访问一些方法:

  • 只要不依赖于记录是否存在如果你不能确定他们会在那里。
    基本上,重做你的假设并修改你现有的代码,以避免依赖强制存在的记录。

  • 职责分离
    不允许不同的用户对同一数据具有相同的创建/编辑/删除权限。例如,采购订单应该属于创建它的用户。不允许其他用户分别删除该订单或其项目。不要实际删除实体,仅允许用户将其标记为'已取消'或'过时',并由于历史原因将其保留在数据库中(或稍后清除)。

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

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

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

  • 使用各种锁定选项(请参阅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代码中查看从其他位置删除记录时发生Error 3167“记录已删除”的位置。
    一旦您知道它在代码中的位置,就可以使用On Error 3167 Goto YourErrHandler来捕获该错误,以便优雅地处理该特定错误(这将取决于您的表单的设计方式以及如何使用数据)。

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

+0

感谢您提供全面的解决方案和想法。我不确定我是否完全同意你写的所有内容,但我认为你的回答在解决问题方面做得很好。 – HK1

0

我通过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(记录中删除),但是当试图访问值属性时,我似乎只能得到上述三个错误。

如果您当前的事件较长,或者像这样运行代码的风险很大,您可以使用类似的技术,但在开始时故意引发错误(dummyvalue = SomeBoundControl.Value应该做到这一点)和然后将错误处理程序中的“Resume Next”更改为“Exit Sub”。

0

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

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

由于它的值似乎如果记录已经被删除,以改变为空字符串,我可以窗体本身上触发

If Me.DateUpdated = "" Then 

(例如跳过关闭过程中的操作)。此检查也可能从其他形式起作用。

相关问题