Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ms access &引用;“数据已更改”;从主窗体步进到子窗体时出错_Ms Access_Vba_Odbc_Ms Access 2007 - Fatal编程技术网

Ms access &引用;“数据已更改”;从主窗体步进到子窗体时出错

Ms access &引用;“数据已更改”;从主窗体步进到子窗体时出错,ms-access,vba,odbc,ms-access-2007,Ms Access,Vba,Odbc,Ms Access 2007,我正在使用SQL Server迁移助手(SSMA)将Access数据库迁移到SQL Server。Access应用程序将继续使用,但将与链接表而不是本地表一起使用 我在迁移后测试中遇到了一个问题,该表单包含多个子表单 测试步骤: 1) 编辑主窗体中的字段 2) 将焦点转移到子表单中的字段 3) 尝试编辑子窗体中的字段 结果:弹出一条错误消息:“数据已更改。在您尝试保存更改之前,另一个用户编辑了此记录并保存了更改。” 一旦错误消息消失,子表单中的字段就可以编辑。如果未编辑主窗体中的字段,则可以编辑

我正在使用SQL Server迁移助手(SSMA)将Access数据库迁移到SQL Server。Access应用程序将继续使用,但将与链接表而不是本地表一起使用

我在迁移后测试中遇到了一个问题,该表单包含多个子表单

测试步骤:

1) 编辑主窗体中的字段

2) 将焦点转移到子表单中的字段

3) 尝试编辑子窗体中的字段

结果:弹出一条错误消息:“数据已更改。在您尝试保存更改之前,另一个用户编辑了此记录并保存了更改。”

一旦错误消息消失,子表单中的字段就可以编辑。如果未编辑主窗体中的字段,则可以编辑子窗体而不显示错误消息

你知道是什么导致了这个错误吗

我已尝试将主窗体记录保存在主窗体上的子窗体控件的Enter事件处理程序中(即,当输入包含子窗体的控件时,此事件发生在主窗体上,而不是在子窗体本身上)。没什么区别。我尝试在同一子窗体控件Enter事件中重新查询主窗体,但不起作用-重新查询主窗体会将焦点从子窗体移开,因此无法编辑

MS论坛建议在子表单的更新后事件中使用Me.Parent.Requery。那也没用

当我进入子表单时,SQLProfiler显示一条更新语句,更新主表单下的表。没有其他语句命中数据库以修改数据

我注意到一件有趣的事情:主窗体的记录源实际上是一个select语句,它将两个表连接在一起。主窗体包含可以更新记录源中每个表中的列的字段。编辑主窗体中更新关系中的子表的字段不会导致“数据已更改”错误。仅当编辑更新关系中父表的字段时,才会发生此错误。我尝试了在两个表中更新不同列的字段。结果是一致的:编辑父表中的记录会导致错误,编辑子表中的记录不会导致错误

子窗体和主窗体之间的链接将子窗体表中的列连接到主窗体记录源中的子表中的列

顺便说一下,主窗体记录源中的表实际上是以1:1的关系联接的(子表中的一条记录对应于父表中的每条记录)。子表只是父表的扩展表


如果我从零开始,我个人不会这样设计系统,但这是我必须要处理的,我希望有一些相当简单的修复方法,不需要对表或表单进行重大的重新设计(考虑到主表单和子表单都有100多个控件)。

经过多次尝试和错误,我解决了这个问题。在主窗体上的子窗体控件的enter事件处理程序中,我重新查询了子窗体本身

例如,主要形式:

Private Sub Subform1_Enter()
    Me.Subform1.Form.Requery
End Sub

我不知道为什么会这样,只知道它会这样。

当表中的记录被更新时,会发生这种情况,但主窗体的记录源尚未刷新以反映更改,因此Access会获取冲突信息并认为记录已被更改。另请参见:

我通过以下方式编写AfterUpdate表单事件来解决此问题:

Private Sub Form_BeforeUpdate(Cancel As Integer)
    cSQL = "update UnderlinedTable set Field1=" & Me.Controls("Field1") & _
        ", Field2=" & Me.Controls("Field2") & _ ' and all other fields in your form
        " where PrimaryKey=" & Me.Recordset.Fields("PrimaryKeyField")
    ' here command to SQL server that executes this cSQL string
    Me.Requery
    Cancel = True 'stop Access updating
end sub

可以使用wriiten universal BeforeUpdate表单事件函数,该函数基于form.recordsource和更改的表单字段自动生成Update语句,这些字段可以从作为参数传递表单的所有AfterUpdate表单事件中调用。这是我为自己做的。

您是否尝试过在SQL Server上创建一个视图,返回与主窗体当前记录源相同的列,并将该视图链接为Access中的“链接表”呢,然后将其用作主窗体的记录源?1:1关系对我来说似乎是可疑的,因为您得到的错误反映了并发用户故障,最有可能是由ODBC发出的。也许您可以尝试删除1:1关系,看看这是否会隔离错误。@Gord Thompson:尝试过,使用Instead Of触发器处理视图中的更新。我发现我必须在访问端的链接表中添加一个唯一的索引,以允许记录可更新。表单的工作方式与最初完全相同,当我更新映射到一个SQL Server表的字段时会出现错误对话框,但当我更新映射到另一个表的字段时不会出现问题。当我关闭错误对话框时,我可以像以前一样更新映射到问题表的字段。因此,现在我怀疑这一定与各个表单控件的属性有关。阅读支持文章时,我似乎遇到了几乎相反的问题:在进入子表单之前,我先编辑了主表单。我怀疑我可以修改那篇文章的答案来解决我的问题:在主窗体中控件的AfterUpdate事件处理程序中,我可以添加Me.Subform1.form.Requery。我还没有尝试过,但我怀疑如果将该行添加到主窗体上的子窗体Enter事件中(这就是我解决问题的方法)。我遇到了相反的问题:从子窗体转到主窗体时出错。因此,在
子表单1\u Exit()
事件中,我放置了
Me.Requery
,它成功了。