[英]Opening 2 recordsets in Access via ODBC SQL Linked Table
I am working on converting our multiple access (2016) files / databases into one consolidated access file with navigation, and the data hosted on a SQL server (2014).我正在努力将我们的多访问 (2016) 文件/数据库转换为一个带有导航的统一访问文件,并将数据托管在 SQL 服务器 (2014) 上。 Currently, we have a button that has the below code, and every time I get to an s.update line, I get the error "new transaction is not allowed because there are other threads running in the session".目前,我们有一个包含以下代码的按钮,每次我到达 s.update 行时,都会收到错误消息“不允许新事务,因为会话中有其他线程正在运行”。
I've been Googling for a day or 2 now and can't seem to get rid of it.我已经在谷歌上搜索了一两天,似乎无法摆脱它。 I read that enabling MARS could help since I have 2 recordsets open, but that did not help.我读到启用 MARS 会有所帮助,因为我打开了 2 个记录集,但这没有帮助。 I do see the "MARS_Connection=Yes" on that tables connection string.我确实在该表连接字符串上看到了“MARS_Connection=Yes”。 I've also read that for loops can cause issues but none of the s.update lines are actually in a for loop.我还读到 for 循环可能会导致问题,但实际上没有 s.update 行在 for 循环中。 I've had trouble finding this issue in relation to Access我很难找到与 Access 相关的这个问题
I'm relearning VBA as I go, I did not write this app and am open for suggestions.我正在重新学习 VBA,我没有编写这个应用程序,我愿意接受建议。
Private Sub cmdNewWeek_Click()
On Error GoTo ErrorHandler
Dim r As DAO.Recordset, s As DAO.Recordset, f As Field, DifferentDate As Boolean, d As Date
d = Date - (Weekday(Date) - 2)
If IsNull(Me.cboSelAtty) Then
MsgBox "Select an attorney first."
cboSelAtty.SetFocus
Else
If IsNull(Me.employee) Then Me.employee = Me.cboSelAtty
DoCmd.RunCommand acCmdSaveRecord
DifferentDate = False
MsgBox cboSelAtty
Set r = CurrentDb.OpenRecordset("Select top 1 * From kt_workload Where employee=" & CSql(cboSelAtty) & " Order By week Desc", dbOpenSnapshot)
Set s = CurrentDb.OpenRecordset("kt_workload", dbOpenDynaset, dbSeeChanges)
If r.EOF Then
s.AddNew
s("employee") = cboSelAtty
s("week") = d
s.Update
s.Close
r.Close
Me.Requery
Exit Sub
ElseIf r("week") >= d Then
If MsgBox("A record for this week already exists. Do you want to enter one for a different week?", vbCritical + vbYesNo) = vbNo Then
r.Close
Exit Sub
Else
DifferentDate = True
End If
End If
s.AddNew
For Each f In r.Fields
If f.Name <> "week" Then s(f.Name) = r(f.Name)
Next
s("week") = IIf(DifferentDate, r("week") + 7, d)
s.Update
s.Close
r.Close
Me.Requery
End If
ErrorHandler:
'Start ODBC error Catch
Dim i As Integer
Dim st As String
For i = 0 To Errors.Count - 1
st = st & Errors(i).Description & vbCrLf
Next i
MsgBox st, vbCritical
'End ODBC error Catch
End Sub
Example Data (I couldn't get the table to format properly for whatever reason): Example Data示例数据(无论出于何种原因,我都无法正确格式化表格):示例数据
In the end, all we are doing is copying the most recent record as the 'test' fields are often similar week to week.最后,我们所做的只是复制最近的记录,因为“测试”字段通常每周都相似。
Edit: I trimmed down the function to the below.编辑:我将功能缩减到以下。 I do get 1 record back from my "r" record as expected.我确实按预期从“r”记录中获得了 1 条记录。 It gets applied to the "s" new record just fine.它可以很好地应用于“s”新记录。
but s.update throws the same error.但 s.update 抛出同样的错误。 Also, if I run this and run a SQL query through SSMS, that query hangs up until the access form throws the error (~60 seconds), so I'm not sure where I am going wrong with the SQL connection side I assume.此外,如果我运行它并通过 SSMS 运行 SQL 查询,该查询将挂起,直到访问表单抛出错误(约 60 秒),所以我不确定我假设的 SQL 连接端哪里出了问题。
Trimmed Down Code:精简代码:
Private Sub cmdNewWeek_Click()
On Error GoTo ErrorHandler
Dim r As DAO.Recordset, s As DAO.Recordset, DifferentDate As Boolean, d As Date
d = Date - (Weekday(Date) - 2)
Set r = CurrentDb.OpenRecordset("Select top 1 * From kt_workload Where employee=" & CSql("jcraig") & " Order By week Desc", dbOpenSnapshot)
Set s = CurrentDb.OpenRecordset("kt_workload", dbOpenDynaset, dbSeeChanges)
s.AddNew
For Each f In r.Fields
If f.Name <> "week" Then s(f.Name) = r(f.Name)
Debug.Print s(f.Name)
Next
s("week") = d
s.Update
s.Close
r.Close
ErrorHandler:
'Start ODBC error Catch
Dim i As Integer
Dim st As String
For i = 0 To Errors.Count - 1
st = st & Errors(i).Description & vbCrLf
Next i
MsgBox st, vbCritical
'End ODBC error Catch
End Sub
Whenever you need a recordset to only read data from, you should open it as snapshot .每当您需要一个仅从中读取数据的记录集时,您应该将其作为快照打开。
In your case you only want to read the first record, so you should also use TOP 1
.在您的情况下,您只想读取第一条记录,因此您还应该使用TOP 1
。
Should you ever have an attorney named O'Brien
, your code will break.如果您有一位名叫O'Brien
的律师,您的密码就会失效。 Use Gustav's CSql()
function when concatenating variables with SQL.将变量与 SQL 连接时,请使用 Gustav 的CSql()
函数。 It handles all strings and prevents SQL injection.它处理所有字符串并防止 SQL 注入。
In summary:总之:
strSql = "Select TOP 1 * From table1 Where employee=" & CSql(cboSelAtty) & " Order By week Desc"
Set r = CurrentDb.OpenRecordset(strSql, dbOpenSnapshot)
This way you won't have conflicting transactions.这样你就不会有冲突的交易。
Note that your ODBC error handling loop should go into an On Error Goto xxx
handler.请注意,您的 ODBC 错误处理循环应该进入On Error Goto xxx
处理程序。
In the end, I think this is some connection issue unique probably to access 2016, SQL Server 2014 and ODBC 17 drivers.最后,我认为这是访问 2016、SQL Server 2014 和 ODBC 17 驱动程序所特有的一些连接问题。 Instead of doing the double recordsource, I'm opening up the read recordsource and just using the values to insert a new record, and then I'll just select this new record.我没有使用双记录源,而是打开读取记录源并仅使用这些值插入新记录,然后我将只选择这条新记录。 It works now at least.它至少现在有效。
sql = "INSERT INTO kt_workload (employee, week, availweek, availMonth, availQtr, activeWeek, activeMonth, activeQtr) VALUES (" & _
CSql(r("employee")) & ",'" & _
r("week") & "'," & _
CSql(r("availweek")) & "," & _
CSql(r("availMonth")) & "," & _
CSql(r("availQtr")) & "," & _
CSql(r("activeWeek")) & "," & _
CSql(r("activeMonth")) & "," & _
CSql(r("activeQtr")) & _
");"
Debug.Print sql
CurrentDb.Execute sql
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.