2017-04-12 5 views
3

Wir implementieren MS SQL Serverlocaldb für Integrationstests.Verbessern Sie die Leistung der Dacpac-Bereitstellung mit C#

Wir erstellen ein Datenbankprojekt und die resultierende Datei dacpac wird kopiert, damit sie vom IntegrationTests-Projekt verwendet werden kann. Bisher haben wir:

DatabaseProject.sqlproj 
    bin/debug/DatabaseProject.dacpac 
IntegrationTests.csproj 
    bin/debug/DatabaseProject.dacpac 

Wir haben einen Montageaufbau in dem IntegrationTests Projekt, bei dem eine neue neue Datenbank erstellt wird und die dacpac auf localdb eingesetzt. Im TearDown wird die Datenbank gelöscht, so dass wir einen deterministischen Status zum Testen haben.

Dies ist der Code, der die dacpac, die DacServices (Microsoft.SqlServer.Dac, System.Data.SqlLocalDb, System.Data.SqlClient) verwendet entfaltet:

public void CreateAndInitializeFromDacpac(
ISqlLocalDbInstance localDbInstance, 
string databaseName, 
string connectionString, 
string dacpacPath) 
{ 

    using (var cx = localDbInstance.CreateConnection()) 
    { 
     cx.Open(); 
     using (var command = new SqlCommand(
      string.Format("CREATE DATABASE {0}", databaseName), cx)) 
      command.ExecuteNonQuery(); 
    } 

    var svc = new DacServices(connectionString); 

    svc.Deploy(
     DacPackage.Load(dacpacPath), 
     databaseName, 
     true 
     ); 
} 

Wir haben jetzt ein paar Datenbank-Projekte, und es dauert ungefähr 8s bereitstellen Jeder. Dies erhöht die Gesamtzeit zum Ausführen der Tests.

Ist es irgendwie möglich, die Bereitstellungsleistung des dacpac zu verbessern?

+1

Visual Studio bietet Möglichkeiten, herauszufinden, welche Anweisungen Zeit brauchen, versuchen Sie, sie fein abzustimmen.Wenn Sie nicht in der Lage sind, sie zu optimieren, versuchen Sie Parallelität zu verwenden, um mehrere Projekte in Parallel – TheGameiswar

+2

müssen Sie wirklich erstellen die Datenbank in einem separaten Schritt? Ohne sich selbst zu testen, vergleicht "dacservices" möglicherweise alle Objekte im dacpac mit ihren Gegenstücken in der leeren Datenbank. –

+0

@GavinCampbell, TheGamesiwar, beide Kommentare waren nützlich und erlaubten mir, die Gesamtzeit für 4 Datenbanken von 25s auf 4.5s zu verringern. – jruizaranguren

Antwort

3

Gavin hat recht!

Sie die Datenbank nicht abzureißen, anstatt die Neue Datenbank erstellen Option verwenden, so SSDT keine Zeit, den Vergleich von zwei Modellen verschwenden muss, wenn es eine ist leer kennt.

Der Code für die Bereitstellung geändert werden sollte:

var dacOptions = new DacDeployOptions { 
       CreateNewDatabase = true 
      }; 

svc.Deploy(
    DacPackage.Load(dacpacPath), 
    databaseName, 
    true, 
    options: dacOptions 
    ); 

Es gibt viele weitere Optimierungen, die SSDT tun können, wenn Sie dieses Flag setzen - wenn Sie Reflektor einen Blick auf Microsoft.Data.Tools.Schema.Sql.dll haben gestört werden kann zu verwenden und Microsoft.Data.Tools.Schema.Sql.Deployment.SqlDeploymentPlanGenerator.OnInitialize(SqlDeployment). Wenn dieses Flag gesetzt ist, überspringt es die gesamte Verbindung zu einer Datenbank und Reverse-Engineer von dem bereitgestellten T-SQL zum Modell.

Dies führt wahrscheinlich zu einem potenziellen Fehler, wo Leute die Modelldatenbank ändern, um einige Objekte aufzunehmen und dann SSDT verwenden, um ein Objekt in der Modelldatenbank zu implementieren, aber als Rand Fälle gehen, klingt es ziemlich niedrig!

Die Leistung kann auch für den Fall mit mehreren Datenbanken verbessert werden, indem der Code mit Parallel.Foreach parallelisiert wird, wie von TheGameiswar vorgeschlagen.

+0

Danke, Ed. Ich habe den benötigten Code hinzugefügt. Wie ich im vorherigen Kommentar hinzugefügt habe, ging ich von 25s auf 4,5s in der Initialisierung von 4 Datenbanken. – jruizaranguren

+0

Ja, ich war mir nicht sicher, ob es irgendwelche "speziellen Überlegungen" für localdb gab, die diesen Ansatz daran hindern würden zu arbeiten; klar gibt es nicht! –

+0

Kleinere Anmerkung: DacPackage-Objekte sind verfügbar. Ich würde empfehlen, sie zu entsorgen. –

Verwandte Themen