Asked by:
ODBC Timeout property doesn't impact how long it takes for a query to timeout

Question
-
Per docs and postings the ODBC Timeout property is supposed to define the number of seconds before an query's odbc connection attempt is ended. But I've experimented and find that it has no impact whatsoever. If I set the property to 2 seconds it still takes anything from 21 to 40 seconds for the sql server Connection failed dialog appears.
All I can think of is that my testing methodology is wrong. I am interested in controlling how to control the number of seconds before the query gives up when a sql server database is not available on the network. To test, I take the sql server offline. I'm wondering if the odbc timeout property is only meant to deal with the timeout value for queries that can actually be invoked?
If that's the case, is there a way to test to see if a sql server is available before attempting to run a query?
Thursday, December 12, 2019 5:07 AM
All replies
-
You can test the ODBC connection by using a “different” path way. This will prevent a ODBC error, and better yet it times out rather fast.
The code is thus this:
Sub Testcon() Dim strCon As String strCon = CurrentDb.TableDefs("dbo_tblHotels").Connect Debug.Print TestLogin(strCon) End Sub
In above, I grab an existing “connection” string.
The function TestLogin() is this:
Public 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. qdf.SQL = "SELECT 1" qdf.Execute TestLogin = True Exit Function TestError: TestLogin = False Exit Function End Function
So the above near times out instant if you can’t get to sql server.
As for the ODBC timeout settings? I don’t believe that there is setting in Access for linked tables. You can however flip a query into sql view mode, then display the property sheet, and there is a default value of 60 seconds.
You can also (I believe) include the timeout as part of the connection string, but the above approach is likely far better anyway.
Give the above a try – it works rather well. It returns True or False.
Regards,
Albert D. Kallal (Access MVP 2003-2017)
Edmonton, Alberta Canada
- Edited by Albert D. Kallal Friday, December 13, 2019 6:10 AM
Friday, December 13, 2019 6:10 AM -
I had a similar issue and wrote the following functions to deal with the problem:
Public Function IsSQLServerInstalled() As Boolean On Error GoTo Err_Handler 'checks registry to see if SQL Server is installed on this computer IsSQLServerInstalled = False strText = GetStringValFromRegistry(HKEY_LOCAL_MACHINE, "SOFTWARE\MICROSOFT\Microsoft SQL Server", "IsListenerActive") 'Debug.Print strText If strText <> "" Then IsSQLServerInstalled = True 'Debug.Print IsSQLServerInstalled Exit_Handler: Exit Function Err_Handler: MsgBox "Error " & Err.Number & " in IsSQLServerInstalled procedure : " & Err.Description Resume Exit_Handler End Function Public Function CheckSQLServerConnection() As Boolean 'returns true if SQL Server is running and the listed database is available 'Otherwise false On Error GoTo Err_Handler Dim cnn As ADODB.Connection CheckSQLServerConnection = False Set cnn = New ADODB.Connection cnn.Open "Provider=SQLOLEDB;Data Source=SERVER;Initial Catalog=DBName;User ID=UserName;Password=PASSWORD" If cnn.State = adStateOpen Then CheckSQLServerConnection = True cnn.Close End If ' Debug.Print CheckSQLServerConnection Exit_Handler: Exit Function Err_Handler: If Err = -2147467259 Then Exit Function 'CheckSQLServerConnection=False MsgBox "Error " & Err.Number & " in CheckSQLServerConnection procedure : " & vbNewLine & _ " " & Err.Description & " ", vbCritical, "SQL Server error" Resume Exit_Handler End Function
Both return boolean values so you can test as follows
If IsSQLServerInstalled = False Or CheckSQLServerConnection = False Then MsgBox "SQL Server is not available, vbCritical, "Connection Error" ....
- Edited by isladogs52 Friday, December 13, 2019 9:30 PM
- Proposed as answer by isladogs52 Saturday, December 21, 2019 11:27 PM
- Unproposed as answer by isladogs52 Saturday, December 21, 2019 11:27 PM
Friday, December 13, 2019 6:51 PM -
I didn't see these responses until now. Both approaches look good, I'll post here with any issues. Thanks to both of you!Friday, January 3, 2020 7:06 PM
-
I've tested both approaches and it takes them 42 seconds to come back with a message that the server isn't available. Albert said his routine would fail due to timeout almost instantly but it's not in my case. 42 seconds is the same timeout that I get without either routine.
I think both of you understood what I was after, so I must be doing something wrong. I just don't see what. I tried reducing the connection timeout in the adodb version and it didn't change anything. Here is that revised connection string
cnn.Open "Provider=SQLNCLI11;Data Source=badservername;Initial Catalog=missingdb;Trusted_Connection=Yes;Timeout=5"
- Edited by lexxicon Sunday, January 5, 2020 3:32 AM
Sunday, January 5, 2020 2:44 AM -
Well, I assume you exhausted most routes here.
Keep in mind that my example was for DAO. I find that if the database don't exist - it comes back instant.
If the server don't, then about 11 seconds. But who knows the complexity of your network setup.
However, the ADO connection object has both a TimeOut, and A ConnectionTime out setting.
(I assume you attempted the ConnectionTimeout setting as the first thing.
However, it might have been missed here.
This works rather nice - and even if the server don't exist at all, it times out in 2 seconds.
Dim rstD As ADODB.Recordset Dim rstDCon As New ADODB.Connection rstDCon.ConnectionString = "Provider=MSOLEDBSQL;Server=ABC-DEF-0006\AXISMIS;Database=TEST3;UID=TEST3;PWD=TEST3" rstDCon.ConnectionTimeout = 2 rstDCon.Open
Note that for some reason, placing the TimeOutconnection as part of the string does not work, but the above does work rather nice for me. And it even works when the server don't exist at all.
Give the above idea a try. You certainly want to do this before you send/attempt any SQL query.
So there is both a Timeout and a TimeoutConnection property for ADO. (I don't believe this exists for DAO).
Give the above idea a try - it works quite nice for me.
Regards,
Albert D. Kallal (Access MVP 2003-2017)
Edmonton, Alberta Canada
Sunday, January 5, 2020 4:24 AM -
Last night after posting I also tried the .ConnectionTimeout setting on a separate line like you have it, in the ado version, and it had no impact.
This am I've done a lot more testing and found...the server I was testing against yesterday has a dns issue so it hasn't been reachable by name for a while, I'd just forgotten. Hitting it by ip address is viable and it even respects the .ConnectionTimeout setting. This is good. Other sql servers are responsive as well.
I was thinking, why would it have been taking so long to fail, since if the issue with reaching the sql server instance by name it would seem to be equivalent to trying to reach a server that is offline. But it must be that the dns issue itself it taking a long time to fail; like it's trying to reach the server but it prevented by some internal tangle.
Thanks isladog52 and albert.
Sunday, January 5, 2020 5:56 PM -
Using my code, it connects instantly if all is OK.
But if SQL Server is not connected, it does take a while to confirm that
I can only suppose Access will keep checking the connection before at some point throwing its hands up in defeat. Better that way than giving up immediately if there is a brief interruption in service.
So I agree there is then a delay - in my case perhaps 10 seconds or so
Sunday, January 5, 2020 9:43 PM -
isladogs52 I found that the .ConnectionTimeout setting does have an impact on how long it takes the function to return false. If I set it to 1 sec, it still takes 3-4 sec to fail, but if I set it to 4 sec it takes 10 sec.Monday, January 6, 2020 5:30 AM