Was ist der schnellste path, um die Verfügbarkeit eines SQL server servers zu überprüfen?

Ich habe ein MS Access Programm in Verwendung an mehreren Standorten. Es verbindet sich mit MS SQL server-Tabellen, aber der servername ist an jedem Standort unterschiedlich. Ich suche den schnellsten path, um die Existenz eines servers zu testing. Der Code, den ich derzeit verwende, sieht so aus:

ShellWait "sc \\" & serverName & " qdescription MSSQLSERVER > " & Qt(fn) FNum = FreeFile() Open fn For Input As #FNum Line Input #FNum, Result Close #FNum Kill fn If InStr(Result, "SUCCESS") Then ... 

ShellWait: führt einen Shell-Befehl aus und wartet darauf, dass er fertig ist
Qt: wickelt einen String in doppelte Anführungszeichen ein
fn: temporäre filenamenvariable

Ich laufe den obigen Code gegen eine list von servernamen (von denen nur einer normal verfügbar ist). Der Code dauert etwa eine Sekunde, wenn der server verfügbar ist und dauert etwa 8 Sekunden für jeden server, der nicht verfügbar ist. Ich würde gerne beide von diesen niedrigeren, wenn möglich, aber vor allem den Fehlerfall bekommen, da dies am häufigsten passiert.

Sie könnten versuchen, eine ADO-Verbindung zu erstellen und das Timeout auf einen niedrigen Wert zu setzen, zB (ungetestet):

 Dim cn As ADODB.Connection Set cn = New ADODB.Connection cn.ConnectionTimeout = 4 ' Wait at most 4 seconds for connection cn.ConnectionString = "Provider=SQLOLEDB.1;Data Source=" & serverName & ";Integrated Security=SSPI" On Error Resume Next cn.Open If Err.Number > 0 Then ... Else cn.Close ... End If On Error Goto 0 ' replace 0 with previously used error handler Auf Fehler Wiederaufnahme Weiter Dim cn As ADODB.Connection Set cn = New ADODB.Connection cn.ConnectionTimeout = 4 ' Wait at most 4 seconds for connection cn.ConnectionString = "Provider=SQLOLEDB.1;Data Source=" & serverName & ";Integrated Security=SSPI" On Error Resume Next cn.Open If Err.Number > 0 Then ... Else cn.Close ... End If On Error Goto 0 ' replace 0 with previously used error handler 

Ich entschuldige mich, wenn ich aus der Reihe bin, seit ich hier neu bin, aber ich wollte einen Vorschlag machen. Sie können tatsächlich die Ausgabe von geschützten Befehlen erfassen, ohne eine Zwischentextdatei mit Windows-API zu verwenden. Ich habe eine kleine classndatei erstellt, die das sauber verpackt ( Link ).

Mit diesem können Sie den Code umgestalten und nicht um die zusätzlichen Kopfschmerzen beim Lesen von fileen zu sorgen.

 Function SQLserverDBExists(serverName As String, DbName As String) As Boolean Dim Result As String Dim cls as new clsRunApp On Error GoTo Err_SQLserverDBExists 'Check for existence of the server Result = cls.RunAppWait_CaptureOutput("nslookup " & serverName) If InStr(Result, "Non-existent domain") Then SQLserverDBExists = False GoTo Exit_SQLserverDBExists End If Result = cls.RunAppWait_CaptureOutput("sc \\" & serverName & " qdescription MSSQLSERVER") If InStr(Result, "SUCCESS") Then With PassThru("SELECT Name FROM sysdatabases " & _ "WHERE Name='" & DbName & "'", "master", serverName) SQLserverDBExists = (Not .EOF) End With End If Exit_SQLserverDBExists: Exit Function Err_SQLserverDBExists: LogError Err.Number, Err.Description, "SQLserverDBExists", "AttachToSQL", , , Erl Resume Exit_SQLserverDBExists End Function 

Die Art, wie ich dies getan habe (in der fernen Vergangenheit) war, um verknüpfte Tafeln zu verwenden und ein User-Formular zu haben, das es ermöglicht, dass ein server zur Laufzeit einmalig ausgewählt wird. Alternativ würden Sie den servernamen in eine configurationsdatei platzieren und die Verbindungszeichenfolge dynamisch erstellen.

 telnet servername 1433 

Die Lösung, die ich schließlich setzte, war, nslookup.exe als Vorläufer zu meinem sc.exe Befehl zu verwenden. Wenn der SQL server server nicht existiert, sagt mir nslookup so sofort. Diese Änderung reduzierte die time, die es brauchte, um auf einem SQL server-Lookup von etwa 8 Sekunden bis weit unter 1 Sekunde zu scheitern. Der Erfolgsfall ist eigentlich etwas länger, aber nicht spürbar. Für diejenigen, die interessiert sein können, hier ist meine endgültige Lösung (hoffentlich der Zweck meiner persönlichen functionen [ShellWait, Qt, PassThru, LogError] wird offensichtlich sein):

UPDATE: Ich habe die function aktualisiert, um dmarucas clsRunApp (mein neues Favoritenklassenmodul) und das von Philippe aufgeworfene Problem über die Arbeit im getrennten Modus zu integrieren. Das Ergebnis ist viel besser als ich ursprünglich gepostet habe und ich möchte ihnen beide für ihre Beiträge danken. Hier ist die function, wie es jetzt steht:

 Function SQLserverDBExists(ComputerName As String, DbName As String) As Boolean Const LocalHost = "127.0.0.1" Dim Result As String, RunApp As New clsRunApp On Error GoTo Err_SQLserverDBExists If ComputerName <> LocalHost And _ ComputerName <> "." And _ ComputerName <> Environ("COMPUTERNAME") Then 'Check for existence of the server using Name server Lookup' Result = RunApp.RunAppWait_CaptureOutput("nslookup " & ComputerName) If InStr(Result, "Non-existent domain") Or _ InStr(Result, "Default servers are not available") Then SQLserverDBExists = False GoTo Exit_SQLserverDBExists End If End If Result = RunApp.RunAppWait_CaptureOutput("sc \\" & ComputerName & " qdescription MSSQLSERVER") If InStr(Result, "SUCCESS") Then With PassThru("SELECT Name FROM sysdatabases " & _ "WHERE Name='" & DbName & "'", "master", ComputerName) SQLserverDBExists = (Not .EOF) End With End If Exit_SQLserverDBExists: Exit Function Err_SQLserverDBExists: LogError Err.Number, Err.Description, "SQLserverDBExists", "AttachToSQL" Resume Exit_SQLserverDBExists End Function 

Anmerkung: Ich realisiere Environ ("COMPUTERNAME") ist nicht eine 100% zuverlässige Art, den Namen des Computers zu bestimmen, also fühlen Sie sich frei, das mit Ihrem eigenen Code zu replace, wenn Sie wollen. Ich denke, der faulen Ansatz ist für seinen Zweck hier ausreichend.

Die hier vorgeschlagene Lösung funktioniert unter bestimmten Bedingungen, wo der Rechner vernetzt ist und ein dns-server zur Verfügung steht. Wenn Ihre Anwendung in beiden verbundenen (wo Sie eine Verbindung zu einem der "Haupt" -server) und den getrennten Modus (wo Sie eine Verbindung zu Ihrer lokalen Kopie der database) herstellen soll, funktionieren, wird diese Lösung nicht tun.

Unsere generische, effiziente aber (ich muss zugeben) nicht-so-smart-Lösung ist bis jetzt eine clientseitige Verbindungstabelle (in der Tat xml-fileen – eine pro Verbindung – im App-Ordner) und lassen Sie den Benutzer die Verbindung an wählen Anfang. je nach dem Benutzer, dem Ort, an dem er arbeitet, und seine Fähigkeit, off-line zu arbeiten, können wir wählen, welche xml-Verbindung Strings auf seinem Computer installieren.

Unsere Idee ist (wenn wir time haben), die IP-Adresse des Computers zu verwenden, um den 'besten' databaseserver zu identifizieren / zu berechnen: Wenn der Computer nicht vernetzt ist, wird die Verbindung auf 'localhost' gesetzt. Andernfalls wird die Verbindung "on the fly" aufgebaut, in einem Netzwerk, in dem databaseserver ein vordefiniertes ip-Suffix erhalten. Also, wenn ein Computer ip ist aaa.bbb.ccc.ddd, wird die Maschine wissen, es muss eine Verbindung zu aaa.bbb.120.132, wo 120.132 ist die vordefinierte database-server-Suffix.