0

我为客户组装了一个小型数据库应用程序。他们希望在 Access 中使用它,因为他们的员工对此感到满意;没问题,他们有 SQL Server 用于后端。粗略地说,它用于跟踪和研究属性继承。

大多数操作发生在“Person”表单上,该表单绑定到一个查询,该查询将 Person 表连接到几个简单的查找表(所有链接到 SQL Server 的表)。有一个用于分配将研究此人的工作人员的子表单,以及一个包含更多子表单(个人详细信息、亲属、链接的法律文件等)的选项卡控件。这里和那里都有一点 VBA,但什么都不是太花哨了。

这是我们看到的问题,到目前为止,客户还无法确定重现(我从来没有能够在我的开发系统上实现它):有时,在用户输入详细信息后Person 表单,他们将集中其中一个子表单分配给工作人员,或设置亲属,然后 Person 表单会突然切换到数据库中的不同记录。

我尝试在 Person 表单上禁用 Form_Activate 的事件过程,它只是根据另一个表单是否对现有记录打开来启用/禁用一个按钮。我已经确认用户不太可能意外点击 Page Up/Page Down 并导航到不同的记录。在单个用户的测试中偶尔也会发生这种情况,所以我怀疑这不是并发问题。

以前有人见过这样的远程吗?我从未体验过 Access 随机切换到不同的记录,并且我已经使用 SQL Server 作为后端制作了多个 Access 应用程序。

4

1 回答 1

0

好吧,我知道发生了什么。我坐在前端,开始向其中输入数据,直到我最终遇到了不稳定的行为。Profiler 一直在运行。当我得到一个意外的记录切换时,我查看了 Profiler 的输出,看到了一个非常明显的确凿证据:

SELECT @@IDENTITY

Access 正在使用该@@IDENTITY变量来获取新插入的记录的 ID。问题:我在这个表上有一个触发器,如果​​一个字段碰巧有一个特定的值,它也会将一条记录插入到另一个表中。当然,第二个表有一个标识列。这是 clobbering @@IDENTITY,当 Access 尝试重新查询它刚刚插入的记录时,它最终会得到一个完全不同的记录(凭借 ID,它几乎可以肯定在 Person 表中具有匹配项)。

我知道理想的情况是消除此触发器并将此自动插入移动到 VBA 代码中,但我需要以最小的更改“使其立即工作”,所以这是我现在要使用的真正可怕的 hack。

在插入附加记录的触发器中,在第一行执行此操作:

DECLARE @id int = @@IDENTITY

然后在触发器的最后,执行以下操作:

DECLARE @sql nvarchar(max) = 'DECLARE @hack TABLE (id int NOT NULL IDENTITY(' + CAST(@id AS varchar) + ', 1), a char(1)); INSERT INTO @hack (a) VALUES (''a'');'
EXEC (@sql)

这会将 的值保存@@IDENTITY在局部变量中,然后(通过动态 SQL)声明一个表变量,其 ID 列从 的前一个值开始@@IDENTITY。它插入一个虚拟行,然后将该变量的值重置为触发器在其他地方插入行之前的值。

这是一个可怕的,可怕的黑客,但它现在就可以了。

于 2013-08-07T17:50:32.380 回答