我使用Access 2013和Sql Server 2012。我已经扩大了访问应用程序到Sql Server使用链接表。我有一个访问查询(不在SQL服务器上),提供了大约4个表的结果。然后,我将其显示在绑定布局/表视图中,其中每一行对应于结果查询的一行。
在布局视图中,用户可以编辑任何一行的数据。一旦用户进行编辑,显然Access将打开一个事务并使其保持打开状态。只要用户处于可编辑布局视图中,作为查询一部分的表就会被锁定。如果其他计算机上的另一个用户正在使用Access,则他们无法编辑任何表(通过任何方法,而不仅仅是相同的布局视图)。第二个用户将在他们的应用程序中暂停30秒,然后最后将得到error…
ODBC-update on a linked table 'TableName' failed.
[Microsoft][ODBC Sql Server DRiver]Query timeout expired (#0)
一旦第一个用户退出布局视图,那么所有内容将再次打开供其他用户编辑。
有办法控制交易吗?也许只是让它更新一行,然后释放事务。
可能必须将布局视图的数据源更改为SQL Server Sproc或view,并且不允许在表中进行编辑。相反,如果用户希望更改一行中的内容,则单击以弹出编辑表单。寻找其他选项
你有几个可能的解决方案。
一种解决方案是使用where子句打开有问题的表单,从而只打开一行,而不是许多行。
如果所讨论的形式不是连续形式,上述建议是可行的。
输入
strInvoice = inputbox("What invoice to work on")
docmd.Openform "frmInvoice",,,"[invoiceNum] = " & strInvoice
因此,假设发票列上有一个索引,将表单限制为一行将解决这个问题。此外,这样的设计往往更加用户友好。我在这里解释这个重要的搜索概念:
http://www.kallal.ca/Search/index.html另一种解决这个问题的方法是用所有记录强制填充表单(从性能的角度来看,这真的是一个坏主意,即使没有SQL服务器启动没有任何类型的where子句,从用户的角度来看,也是一个坏主意,从性能的角度来看).
表锁经常发生的原因是表单开始从SQL server提取数据,但是Access说嘿,等一下,我有足够的数据-但是在SQL server上启动的查询已经触发了一些表锁,并假设所有行都将返回给客户端(因此客户端停止记录流是真正导致锁的原因)。为了避免这个问题,你可以最后执行一次移动来拉出所有的记录,这样就会消除(释放)表锁。
在form - on-load事件中,你可以输入:
me.recordset.MoveLast
me.recordset.MoveFirst
如前所述,这里的问题是将所有记录拉入表单首先是一个非常糟糕的设计。
最后一点:
另一种消除表锁的方法是将查询构建为视图SQL服务器端,并包含NOLOCK提示。然后设置到视图的链接,表单不是基于本地查询,而是基于视图的查询。既然视图有NOLOCK提示,那么你就不需要上面提到的moveast/movefirst建议了。
因此,在这里的几个解决方案中,将表单打开到一个记录确实是推荐的解决方案。我的意思是,当你走到一台即时柜员机前,它不会下载每个账户,然后问你要处理哪个账户。当你使用像谷歌这样的搜索引擎时,它不会下载整个互联网,然后问你要搜索什么。就连站在公共汽车站的老太太都能算出来,更不用说写软件的人了!
所以当你在Access中设计和构建表单时,将表中的所有记录下载到表单中然后让用户搜索是没有意义的。所以用户需要提示什么工作之前的表单被加载,如果你使用一个where子句打开表单时,即使表单绑定到一个大型的SQL服务器链接表只有记录匹配where子句将被拉下到该表单。
如果不使用where子句,那么如前所述,锁定问题就会出现。
作为临时修复,尝试在表单on-load中使用movelast/movefirst,因为这应该可以修复锁定问题。然而,从长期来看,我建议使用where子句,或者考虑视图的想法。
请注意,如果您有基于这4个表中的任何一个的组合框,那么您将再次发现锁定问题,因为组合框将请求数据(并且SQL服务器在该请求期间放置表锁)。并且再次访问将告诉sql server,请停止加载组合框,因为所有行还不是必需的(但太晚了,因为表锁已经发生)。
因此,如果基于所使用的任何表在该形式中有任何组合框,那么您将再次发现表锁发生。在这些情况下,我再次建议将组合框基于带有NO LOCK提示的传递查询,或者基于带有NO - LOCK提示的视图。
所以检查表单中是否有任何基于这些表的组合框——它们也会导致表锁定。