Ist es möglich, eine Verbindung zu SQL server ohne Angabe einer database herzustellen?

Ich versuche, einige Unit-Tests für meinen Code zu schreiben, die mit SQL server für Persistenz verbunden sind, aber ich möchte in der Lage sein, meine Unit-Tests durch einfaches Zeigen auf eine SQL server-Instanz ausführen und lassen Sie die Tests ihre eigene database erstellen um Tests auszuführen, so dass nach jedem Test kann es einfach die database und dann auf Setup vor dem nächsten Test neu zu erstellen, so dass ich weiß, es gibt keine Legacy-data oder Strukturen übrig von einem früheren Test, die den nächsten Test.

Kurz gesagt: nein, das kannst du nicht. Sie können die database aus der Verbindungszeichenfolge auslassen, aber in diesem Fall wird diese Verbindung zu der konfigurierten Standarddatenbank der Anmeldung hergestellt, die eine Verbindung zu SQL server herstellt (und diese Standarddatenbank muss zum timepunkt der Verbindung vorhanden sein gemacht)

Wenn du dieses Szenario haben möchtest, musst du

  1. erstmals mit deinem testdb und database- master und deinen neuen testdb erstellen (oder was auch immer es heißt)

  2. trennen

  3. in deinen Tests eine Verbindung zur Instanz und zur testdb database herstellen

Besser noch: Verwenden Sie ein spöttisches Framework von einer Art, so dass Sie nicht einmal brauchen eine aktuelle database in Ihrem Test-Szenario!

Was Sie erreichen wollen, ist mit einem spöttischen Rahmen möglich. In diesem Fall müssen Sie nicht einmal "eine Verbindung zu einer database" herstellen, Sie verspotten einfach die Rückgabewerte, die die database zurückgeben soll, damit Sie Ihren "db-Handler testing können " Implementierung.

Es gibt mehrere zu wählen, wenn es um C # kommt, kann ich empfehlen Rhino Mocks und Moq, um zwei zu nennen. Hier ist eine Frage, die ein bisschen mehr beschreibt; https://stackoverflow.com/questions/37359/what-c-sharp-mocking-framework-to-use

Warum nicht die gleiche benannte database für Tests gewidmet? und schaffe es jedes Mal. Auf diese Weise musst du dich nicht mit Verbindungszeichenfolgen durchsetzen – es ist immer dasselbe.

Und doch gibt es eine bessere Lösung: In all deinen Tests starten Sie die Transaktion, testing Sie Ihren Test, wo Ihre data durcheinander gebracht werden. Sobald Sie den Test überprüft haben (oder fehlgeschlagen), entfernen Sie die Transaktion. Auf diese Weise musst du deine Tests nicht für jeden Test löschen, denn die data werden nie geändert.

Aber du musst dafür sorgen, dass das Schema in der Testdatenbank immer aktuell ist. Also musst du die Testdatenbank löschen, wenn dein Schema geändert wird.

Ich habe über database-Tests bloggen und wie wir mit Entity Framework-Migrationen umgehen. Dies könnte nicht ganz auf Ihre Situation anwendbar sein, könnte aber mit Ideen helfen.

In Bezug auf die Verwendung von Spott in Ihre Tests – ja das ist absolut gültig Vorschlag und sollte die meiste time befolgt werden. Es sei denn, Sie versuchen, die database-Ebene zu testing. In diesem Fall werden keine Spuren Sie sparen, und Sie müssen nur zur DB gehen. Viele Male habe ich versucht, DbContext in EF zu verspotten, aber niemals gelungen, ein realistisches DB-Verhalten zu simulieren. So ging zur DB war einfacher für mich, anstatt Simulation DB-Mock.

Ich würde SQL server Management Objects für die Aufgabe verwenden. Es ist server- und database-APIs braucht nicht unbedingt eine Verbindungszeichenfolge, aber ich denke, du musst noch eine database angeben. Sie können dafür master . (Überprüfen Sie die Antwort von jeroenh auf das Erstellen von object mit SMO-API )

Übrigens, wenn du mit .Net 4.0.2 und höher bist, kannst du auch LocalDB nutzen, was noch besser ist.

Bearbeiten: Beachten Sie, dass eigentlich LocalDB eine SQL server 2012 function ist, aber Sie benötigen immer noch .Net Framework> 4.0.2, um es nutzen zu können .

Ich benutze die folgende class, um das OP-Szenario zu erleichtern:

 public class MsSqlDatabaseCreator { public void Create(string connectionstring) { if (DatabaseExists(connectionstring)) { DropDatabase(connectionstring); } CreateDatabase(connectionstring); } private static void CreateDatabase(string connectionString) { var sqlConnectionStringBuilder = new SqlConnectionStringBuilder(connectionString); var databaseName = sqlConnectionStringBuilder.InitialCatalog; sqlConnectionStringBuilder.InitialCatalog = "master"; using (var sqlConnection = new SqlConnection(sqlConnectionStringBuilder.ConnectionString)) { sqlConnection.Open(); using (var sqlCommand = sqlConnection.CreateCommand()) { sqlCommand.CommandText = $"CREATE DATABASE {databaseName}"; sqlCommand.ExecuteNonQuery(); } } } private static bool DatabaseExists(string connectionString) { var sqlConnectionStringBuilder = new SqlConnectionStringBuilder(connectionString); var databaseName = sqlConnectionStringBuilder.InitialCatalog; sqlConnectionStringBuilder.InitialCatalog = "master"; using (var sqlConnection = new SqlConnection(sqlConnectionStringBuilder.ConnectionString)) { sqlConnection.Open(); using (var command = sqlConnection.CreateCommand()) { command.CommandText = $"SELECT db_id('{databaseName}')"; return command.ExecuteScalar() != DBNull.Value; } } } private static void DropDatabase(string connectionString) { var sqlConnectionStringBuilder = new SqlConnectionStringBuilder(connectionString); var databaseName = sqlConnectionStringBuilder.InitialCatalog; sqlConnectionStringBuilder.InitialCatalog = "master"; using (var sqlConnection = new SqlConnection(sqlConnectionStringBuilder.ConnectionString)) { sqlConnection.Open(); using (var sqlCommand = sqlConnection.CreateCommand()) { sqlCommand.CommandText = $@" ALTER DATABASE {databaseName} SET SINGLE_USER WITH ROLLBACK IMMEDIATE; DROP DATABASE [{databaseName}] "; sqlCommand.ExecuteNonQuery(); } } } } 

Der wichtige Teil ist das Umschalten des databasenamens (Anfangskatalog) zum Master. Auf diese Weise kannst du nur einen Anschlussstring haben.