MS Access dropping connection to ODBC tables after long period of inactivity - ms-access

I have an Access 2010 front end which has multiple linked tables on a local MySQL server (Windows) connected via ODBC. Most of the time it works just fine however Access drops the connection if left for several hours with Access open but not being used. When a form is opened again I get an ODBC error.
The problem is fixed by closing Access and opening it again.
I'm guessing that it's a timeout issue but I'm not an Access expert. It seems that I need a way of checking for a valid ODBC connection and if necessary, re-connecting?
Any ideas?

Unfortunately there is no readily available way at this point in time to resolve this issue.
Often the issue is the result of power management on the computer. If the computer goes to sleep, or the computer puts the network card to sleep, then you in trouble and you have to re-start Access.
So if your computer sleeps, or puts the network card to sleep, you often loose the connection - once lost you have to re-start.
Also some hardware with windows 10 also has issues since the DEFAULT setting for windows 10 is fast start up (this means a copy of the kernel and MOST important a copy of the drivers loaded and initialized are written to disk and used to shorten boot/start up time).
If you seeing this issue on windows 10, then I would consider disabling fast start up as that will “always” force a cold re-initializing of the drivers (such as those for the network card). I would also consider turning off the “sleep” mode if that’s been determined to be an issue here (and that such offending computers are seeing this issue after a wake up).
Edit: I should also point out that some "test" for a ODBC connection will not fix this issue since as noted, once lost, you have to re-start Access.

You could try an old trick - at launch to open a simple form bound to a table and hide that form, and leave it open.

I rarely worked during several hours on MySQL tables so I never experienced this issue, but IMO it sounds like a driver-related issue or feature.
Waht I would do in this case is to refresh the tables' connections in VBA, looping over your TableDef objects.
Make a hidden form with a 1 hour timer for instance, and add the following code in the form_timer:
Sub Form_Timer()
Dim tDef As DAO.TableDef
Dim strConString As String
Dim strMySQLServer As String
Dim strMySQLDB As String
Dim strMySQLUser As String
Dim strMySQLPass As String
' ADAPT THIS :
strMySQLServer = ""
strMySQLDB = ""
strMySQLUser = ""
strMySQLPass = ""
strConString = "ODBC;DRIVER={MySQL ODBC 5.1 Driver};Server=" & strMySQLServer & ";Database=" & strMySQLDB & ";Uid=" & strMySQLUser & ";Pwd=" & strMySQLPass & ";Option=3"
For Each tDef In CurrentDb.TableDefs
' You probably have to adapt the folowing if
' Debug and inspect the connection string of your actual MySQL Linked tables
If Left(tDef.Connect, 4) = "ODBC" And InStr(tDef.Connect, "MySQL") > 0 Then
tDef.Connect = strConString
tDef.RefreshLink
End If
Next tDef
End Sub
Watch my comments carefully, espacially if you have linked table to several MySQL databases. It will break some of them without adaptation.
You might also have to adapt the connection string following your MySQL driver, or to use the DSN entry that you specified in the ODBC control panel instead.

Related

use login to allow use of dsnless links

i'm using dsnless links in access 2019 to a mysql instance on aws. I have an Access login form, which passes uid & password to a connection string in VBA, and connects and executes simple "select 1".
All along, i assumed the credentials from my access input form were being used to check against my MYSQL users, BUT...it looks to maybe use a cached user/password instead? When i enter a wrong password into my access login form, it still successfully connects and executes the qdf / sql query.
(i can 'watch' the connection string in vba does have the wrong password)
how can i force odbc to authenticate using the actual id & password actually being sent in connection string??
This simple login form has worked, but just realizing now it will pass a wrong password from my access form, but yet still connect and execute the sql...
Function TestLogin(uid As String, pwd As String) As Boolean
On Error GoTo testerror
Dim dbs As DAO.Database
Dim qdf As DAO.QueryDef
Dim RST As DAO.Recordset
Dim strcon As String
Dim errX As DAO.Error
Dim strsql As String
Dim strRW
strcon = "ODBC; Driver=MySQL ODBC 8.0 Unicode Driver;" & _
"SERVER={xxx};DATABASE=xxx;PORT=3306;" & _
"UID=" & uid & "; PWD=" & pwd & ";COLUMN_SIZE_S32=1;DFLT_BIGINT_BIND_STR=1;OPTION=3"
Set dbs = CurrentDb()
dbs.QueryTimeout = 5
Set qdf = dbs.CreateQueryDef("")
qdf.Connect = strcon
qdf.sql = "SELECT current_user"
Set RST = qdf.OpenRecordset(dbOpenSnapshot, dbSQLPassThrough)
TestLogin = True
mysqlUser = uid
floor = DLookup("floor", "tblxx", "user ='" & mysqlUser & "'")
Set qdf = Nothing
Set RST = Nothing
DoCmd.Close
DoCmd.OpenForm "Switchboard"
exit_errorTrap:
Set qdf = Nothing
Set RST = Nothing
Exit Function
Ok, the WAY this works can be confusing.
On application start up we asume you do not by accient (or intention) let any form, any VBA code that runs to touch, or logon or use IN ANY POSSBILE way on startup.
Ok, with above? If you linked the tables correct without UID/Password, if you touch, or even try to open a table from the nav pane? you SHOULD get a ODBC prompt. So, test the above - hold down shift key during startup - NO CODE or NO touch of a linked table is assumed here.
Now, click on a linked table - if the table opens, then you screwed up your table linking, and you DO NOT need the logon, then, right????
Next issue - and READ VERY careful.
If you execute a VALID logon (with your logon code), then ONCE you done this, the correct connection is cached - you can NOT IN ANY POSSBILE way blow out, remove, or re-set that cache.
If AFTER having executed ANY valid logon?
Then ANY ADTIONAL attempted logons (say with your logon code) WILL ALWAYS return true and valid. INCLUDING WRONG logons!!!! (they STILL return true!!!!).
The above information thus means some very significant issue's.
to clear hte logon, you will have to (must) exit Access. You thus can't crete a logout form - you must EXIT applcation.
Worse yet, you BETTER ALWAYS BUT ALWAYS BUT ALWAYS exit access first to clear that cache when developing and testing re-linking of tables. If you at any point in time during development by intention (or accident) open a linked table, and enter uid/password (or do so via code, or do so by JUST clicking on a linked table that DOES and DID save the uid/password?.
Then if you decide to re-link tables - EVEN WITH a incorrect UID/password, they WILL REPORT they linked ok!!!! - but they did not!!!! Even during re-link, if you use the wrong UID/Password, you are screwed, since access will in fact use the cached one (if your uid/password are wrong!!!!).
So, you first have to 100%, if not 200% do the first test above - check, double check/ triple check that linked tables do NOT WORK when clicked on.
Now, run your VBA logon.
Now, cliking on any linked table should work. But as noted, ONCE you touched, or logged on (by any possbile means), the UID/PW is cached, and will remain so for that session until such time you exit access.
What this means is you get ONCE chance to logon. They can fail, but the instant you achieve ONE successful logon, then ALL FURTHER attempts at logons WILL WORK - even if incorrect.
In summary:
You can prompt for a logon.
you can do this without having to re-link tables.
All linked tables, and EVEN pass-though queries will use that cached logon.
You MUST exit access to clear this cache, and thus it is IMPOSSILE to now launch your custom logon form and logon with a different user, since the previous user remains cached.
This also as noted means during deveopment, to link tables without uid/pw, you need to exit Access. launch access (without ANY POSSBILE touch of linked tables/data).
You then execute your logon. You THEN re-link tables without UID/Password. Then you have to exit access, re-launch (shift startup by-pass). Now click on a table - it should fail - prompt for odbc.
But, if you exit, shift- by pass startup. Execute your logon. Now click on a linked table - it should work. If it does not, or the first test (without a logon DID work, then as noted, you have royal screwed up something here.
so, for wrong/incorrect logons? You can continue trying to log on.
But ONCE you have logged on - that's quite much the end of this process. Any further attempts at logons will ALWAYS work - even for totaly wrong logons - you have to exit to clear the PW cache.
you also as a result can thus not use two cached passwords - say some tables linked as read only, and some tables linked as read/write (based on different uid/pw). and the reason is you can't control which logon will be used - and access will thus choose the read/write logon.
So, I suppose the most simple explain?
Once a uid/pw is cached, then you can and will be able to use all linked tables regardless of what uid/logon you attempt to use. And EVEN if at that point in time you did decide to run your re-link code? it will re-link JUST fine, even if you supply a incorrect uid/password. But, be carful!!! - you can in some cases thus re-link, check that the tables worked, but when you exit, and re-enter - you find those linked tables now don't work!!!
So, be VERY careful, if not outright SUPER careful when you re-link, especially if you been messing around with connections - you have to exit access, shift by-pass startup. and THEN re-link your tables. One stray cached uid/password, and you are in heaps of trouble - since things will work, and not make any sense at all.
keeping the above simple concept in mind - all will and should now make sense.
I been using this code:
Function TestLogin(strCon As String) As Boolean
On Error GoTo TestError
Dim dbs As DAO.Database
Dim qdf As DAO.QueryDef
Set dbs = CurrentDb()
Set qdf = dbs.CreateQueryDef("")
qdf.connect = strCon
qdf.ReturnsRecords = False
'Any VALID SQL statement that runs on server will work below.
' this does assume user has enough rights to query built in
' system tables
qdf.sql = "SELECT 1 "
qdf.Execute
TestLogin = True
Exit Function
TestError:
TestLogin = False
Exit Function
End Function
now you used a pass-though query - and I never done/use that before - and don't think it will work. You have to use above format.

MS Access back-end database corruption

I have written an MS-Access application and split the database. In order to improve performance when it is being used by multiple concurrent users on a network (as suggested by this), the front-end creates a persistent connection to the back-end using the following routine:
Public theOpenDb As dao.Database
Public Sub OpenTheDatabase(pfInit As Boolean, Optional databasePath As Variant)
' Open a handle to a database and keep it open during the entire time the application runs.
' Params : pfInit TRUE to initialize (call when application starts)
' FALSE to close (call when application ends)
' Source : Total Visual SourceBook
Dim strMsg As String
If pfInit Then
On Error Resume Next
Set theOpenDb = OpenDatabase(databasePath)
If Err.number > 0 Then
strMsg = "Trouble opening database: " & databasePath & vbCrLf & _
"Make sure the drive is available." & vbCrLf & _
"Error: " & Err.Description & " (" & Err.number & ")"
End If
On Error GoTo 0
If strMsg <> "" Then
MsgBox strMsg
End If
Else
On Error Resume Next
theOpenDb.Close
Set theOpenDb = Nothing
End If
End Sub
Some of my users report repeatedly receiving "unrecognized database format" errors in their back-end databases. The databases have all been recoverable via compact and repair, but this problem is still very frustrating to them.
I read here:
Do not hold connections open: Always remember to close the Microsoft Access database connections after finishing your work. Open Access database connections always have the chance of becoming corrupt if network connections are lost.
Does maintaining a persistent connection between my front-end and back-end increase the risk of database corruption?
Well like always, too little information without context?
A persistent connection NEVER causes corruption.
Always remember to close the Microsoft Access database connections after finishing your work.
Right, but your persistent connection is NEVER doing any work!!!!
So, if you write some code to open a table, do some work, then you close that recordset and connection. This has ZERO ZERO to do with the code that holds the connection open. That connection is NEVER doing any work, and NEVER updating any data - so the suggestion does not apply here.
So, yes, you most certainly want to clean up your update code, and routines that say open a table, do work, and THEN it should close things up like suggested. But for a connection that just sits there and does nothing and no work? It not going to cause a corruption, and if anything it will reduce corruptions.
As always, a bit of information without context is worse then not having that information at all. So, I borrowed a rope from you? Well, I failed to mentioned that your cow was attached to that rope!!! So, context here is important.
So, what that reads should really say:
Do not hold connections open that are doing useful work. Do your updates or whatever, and then tidy up and close up after you are done. But that suggeest has ZERO ZERO to do with some code that keeps open a persistent connection and does zero work, and hence has zero to tidy up and close up after it done it work. So, the persistent connection not doing any work, not doing any updates, and hence it has nothing to clean up, and has ZERO abilities to keep a pending disk write (table write) open and un-finished should Access crash.

VB script in Access 2013 produces "out of memory" error in QuickBooks Enterprise 14

I'll start by saying that VB is not my first language. I've written a very basic script that queries a list of QuickBooks items for deletion, however, after about 400 deletions QuickBooks pops up an error: "Out of memory. May not complete this operation." I can click the OK button and it will continue to update the records, one by one, however, I am trying to delete about 170,000 of them so this is not an option.
I am connecting to the QuickBooks database using FlexQuarters QODBC. I have followed the steps in this article to increase the InitialCache and MaxCache settings for the QuickBooks DB SERVER, however, it seems that this only applies to the DB SERVER and not to the application cache. The settings appear in the QuickBooks information screen as follows:
File Information
Initial Cache: 2048
Max Cache Size: 3769
Local Server Information
Initial Cache: 2048
Cache: 12288
Those numbers are in MB, so I'm assuming the cache sizes should be more than sufficient to perform the operation without memory error. The max cache represents about 18% of the total available RAM on the machine.
I'm wondering... is there a way to modify this VB script in such a way as to clear the application cache in QuickBooks after say, 250 operations?
Private Sub Command0_Click()
Set cn = CreateObject("ADODB.Connection")
Dim rs As Recordset
Dim iCounter As Integer
Set rs = CurrentDb.OpenRecordset("SELECT ListID FROM ItemsForDeletion")
cn.ConnectionString = "DSN=QuickBooks Data QRemote"
While Not rs.EOF And iCounter < 250
cn.Open
cn.Execute ("DELETE FROM ItemInventory WHERE ListID='" & rs!ListID & "'")
cn.Close
CurrentDb.Execute ("DELETE FROM ItemsForDeletion WHERE ListID='" & rs!ListID & "'")
iCounter = iCounter + 1
rs.MoveNext
Wend
rs.Close
End Sub
Just a note, the original code included only one cn.Open and one cn.Close statement outside of the WHILE loop, but was told by an Intuit developer that this way might be less likely to produce a memory error (which obviously did not pan out).
Hoping there is a way around this. I do not wish to run this process 400 times, rebooting every time, as is currently the only way through the issue.
UPDATE
Posted this question on SuperUser and confirmed that the application cache settings in QB cannot be altered, though my machine has about 59GB of free RAM.
At this point, I'm wondering if there is any way that I a VB script can reset the application cache or limit the size to which it grows as a result of the queries presented above?
UPDATE
For those out there who are experiencing the same issue, I was able to find a "workaround", not one that solves the underlying issue, but that gets around the result of the problem expediently.
A simple macro recorder (in this case I used JitBit) to sniff for the warning message box that pops up with QB is out of memory, and force kill the QuickBooks task, reopen it, restart the QODBC driver, and reinitiate the Access query.
A hacked solution, but at least I don't need to sit a my computer for the next 80 hours doing this. Thank God for macros!
Still hoping that there is an answer to the underlying issue out there.
UPDATE
Attempted installing SQL Server on the machine, with a different version of the QODBC database driver (server driver instead of desktop driver). Initially, seemed to be running, but after further inspection the new configuration simply resulted in a memory leak that caused the "QBW32.EXE -silent" process to repeatedly overload and restart. No records were deleted.
We're essentially out of business until this issue is resolved. Please, if anyone has any thoughts on the matter, really need some help here.
You might be able to work around the issue by actually creating and destroying the connection object inside the loop. (Currently you are opening and closing the connection, but you are still using the same connection object for each iteration.)
I'd be interested if something like this worked better for you:
While Not rs.EOF
Set cn = CreateObject("ADODB.Connection")
cn.Open "DSN=QuickBooks Data QRemote"
cn.Execute "DELETE FROM ItemInventory WHERE ListID='" & rs!ListID & "'"
cn.Close
Set cn = Nothing
CurrentDb.Execute "DELETE FROM ItemsForDeletion WHERE ListID='" & rs!ListID & "'"
iCounter = iCounter + 1
rs.MoveNext
Wend
Also, as a side-note, it is usually not a good idea to use a separate SQL statement to delete records from a table/query while you are iterating through it via a Recordset. Instead of
CurrentDb.Execute "DELETE FROM ItemsForDeletion WHERE ListID='" & rs!ListID & "'"
it might be safer and more convenient to just do
rs.Delete
The nightmare is over. After contacting every top QB specialist for assistance, and after being told that performing a database query of this size on a QuickBooks file was impossible without further corrupting our file or messing up the sync with our CRM, there was one who was able to get the job done. We're now finally in sync with the web CRM and all operations have been performed flawlessly, with all corruption eliminated from our file.
Matt Clark of QBorNotQB.com made it happen. Anyone having a similar issue, this is your only viable solution, I assure you. After MONTHS trying to get around the miniscule application cache in QuickBooks, this guy was able to do it in less than 36 hours.

Connecting an Access form to a SQL Server

I have been working on a project that is near completion but this final part is causing me some headaches because I have never done this before and I am having a hard time finding the research to help get me going I have no idea where to even begin. The project is as follows: (this is the context of the email from my boss)
You will need to look up how to check for connectivity using vba. The server you will connect to is the HRLearnDev. I have an access form I will send you that has the connection info in macros on it, where I did something similar. The difference is, my program connected directly to the server. Yours will need to write to a local table, do a check for connectivity when the access file is opened, or every few minutes or something, and if the check reads that there is a connection, write the data from the local server table to the remote server table, then truncate the local table.
I am really stuck and I am running out of options so any insight on where to start to look that is for beginners would be greatly appreciated.
Try something like this to check the connection:
Public Sub TestConnection()
Dim cnn As ADODB.Connection
Dim canConnect As Boolean
Set cnn = New ADODB.Connection
cnn.Provider = "sqloledb"
cnn.Open "Data Source=HRLearnDev;Initial Catalog=YourTableName;UserID=userID;Password='password';"
If cnn.State = adStateOpen Then
canConnect = True
cnn.Close
End If
MsgBox "Can you connect? - " & canConnect
End Sub
Honestly, this is obviously a homework problem and I don't think giving you the entire answer would be the right thing to do, but that should get you started.

Connection to MSAccess DB unable to perform more than one query

I'm setting up my first locally hosted website on a new machine in a long time and to be honest am not very familiar with all the manual settings that get configured now. My last set up was on a Windows XP box and it seemed to "just work" when I enabled IIS. Not so this time.
My latest issues is with connecting to a MSAccess DB. I have a VERY BASIC page with a form that contains 1 input. I check the DB to make sure it doesn't already contain the value and if not, then write the value to the DB. I get the following error:
Provider error '80004005'
Unspecified error
/trips/admin_add_hotel.asp, line 22
I've researched online and everything seems to point to it being a permissions issue. However, I can remove the second portion of the code (the writing) and the page will return fine. If I try to run the page again or refresh, I'll then get the error. This to me says the user has read access. Now, I can wait a little bit and remove the first portion of the code and just write to the DB and it will work fine. Again, to me signifying that the user has write access. However, if I try to run it again... same error.
Here's the ASP code:
<!--#include file="includefile.asp"-->
<%
if Request("action") = "submit" then
'make sure hotel name is filled in
if Request("fhotel") <> "" then
fhotel = Request("fhotel")
'make sure hotel doesn't already exist in DB
sql = "SELECT hotel_id FROM hotels WHERE hotel_name = '" & Replace(fhotel, "'", "''") & "'"
RS.Open sql, ConnectString
if NOT RS.EOF then
Session("msg") = "Hotel already exists"
End if
RS.Close
'add hotel to DB
if Session("msg") = "" then
sql = "INSERT INTO hotels (hotel_name) VALUES ('" & Replace(fhotel, "'", "''") & "')"
Conn.Open ConnectString
Conn.Execute sql
Conn.Close
Session("msg") = "Hotel added successfully"
fhotel = ""
End if
Else
Session("msg") = "Hotel left blank"
End if
Set RS = Nothing
Set Conn = Nothing
End if
%>
My include file is:
<%
ConnectString = "DSN=ConnectionDSN; Uid=username; Pwd=password"
Set RS = Server.CreateObject("ADODB.Recordset")
Set Conn = Server.CreateObject("ADODB.Connection")
%>
My DB has 1 table with two columns:
hotel_id [AUTONUMBER]
hotel_name [TEXT (255)]
Here are my system details:
Windows 7 Pro 64-bit (although connections have been set up for 32-bit based on what I've found online)
IIS 7.5
Just to make sure it wasn't a permissions issue, I've temporarily allowed the 'Everyone' user full access to that folder.
Any help is appreciated. I believe this is the last hurdle I have to get thing fully up and running.
Thanks in advance.
A few things:
32bit vs 64bits: make absolutely sure that your application is set explicitly to x86, not AnyCPU. Also make sure that if you are using the newer .accdb you have the Access Database Engine drivers installed.
Permissions: as Dan Matheus said, make sur that the process under which IIS runs has write permission to the folder. It may not be enough that you set it to Everyone, make sure that your web app can actually create a file in that folder (test this assumption in your code).
Make sure your connection string for the Access file explicitly mentions shared access, and not exclusive access, otherwise, if different processes have the
Keep a connection to the database open all the time to avoid issues with the quick creation/deletion of the lock file.
The Jet/ACE database driver needs to create the lock file every time you access the file (if it is in shared mode). Issues will arise when your app quickly access/releases the database file and the lock file is created/deleted too often.
First it will greatly slow down your performance, and second you will get strange errors.
Just keep a connection open to the database and close it when your app shutdowns.
For more information about the points above, see this:
Intermittent “System resource exceeded” exception for OleDB connection to Microsoft Access data file