2012-05-03 20 views
14

Devo essere in grado di pubblicare un progetto SSDT a livello di codice. Sto cercando di utilizzare Microsoft.Build per farlo, ma non riesco a trovare alcuna documentazione. Sembra piuttosto semplice creare il .dacpac, ma come potrei pubblicare su un database esistente o almeno su un file .sql. L'idea è di farlo fare quello che fa quando faccio clic destro sul progetto e selezionare pubblicare. Dovrebbe essere confrontato con un database selezionato e generare uno script di aggiornamento.Utilizzo di Microsoft.Build.Evaluation per pubblicare un progetto di database (.sqlproj)

Questo è ciò che ho finora per creare il .dacpac:

partial class DBDeploy 
{ 
    Project project; 


    internal void publishChanges() 
    { 
    Console.WriteLine("Building project " + ProjectPath); 
    Stopwatch sw = new Stopwatch(); 
    sw.Start(); 

    project = ProjectCollection.GlobalProjectCollection.LoadProject(ProjectPath); 
    project.Build(); 
    //at this point the .dacpac is built and put in the debug folder for the project 

    sw.Stop(); 
    Console.WriteLine("Project build Complete. Total time: {0}", sw.Elapsed.ToString()); 

    } 
} 

In sostanza io sto cercando di fare ciò che questo MSBuild Example spettacoli ma nel codice.

Mi dispiace che questo è tutto ciò che ho. La documentazione sulle classi di build è molto scarsa. Qualsiasi aiuto sarebbe apprezzato.

Grazie.

risposta

3

Abbiamo bisogno di un modo per dire a msbuild come e dove pubblicare. Apri il tuo progetto in Visual Studio e inizia a Publish it. Immettere tutte le informazioni necessarie nella finestra di dialogo, comprese le informazioni sulla connessione DB e eventuali valori variabili SQLCMD personalizzati. Save Profile As... in un file, ad es. Northwind.publish.xml. (. Si può quindi Cancel) Ora possiamo usare questo e il file di progetto per costruire e pubblicare:

// Create a logger. 
FileLogger logger = new FileLogger(); 
logger.Parameters = @"logfile=Northwind.msbuild.log"; 
// Set up properties. 
var projects = ProjectCollection.GlobalProjectCollection; 
projects.SetGlobalProperty("Configuration", "Debug"); 
projects.SetGlobalProperty("SqlPublishProfilePath", @"Northwind.publish.xml"); 
// Load and build project. 
var dbProject = ProjectCollection.GlobalProjectCollection.LoadProject(@"Northwind.sqlproj"); 
dbProject.Build(new[]{"Build", "Publish"}, new[]{logger}); 

Questo può richiedere un po 'e può apparire a bloccarsi. Essere pazientare. :)

+1

Avevo bisogno di fare riferimento sia agli assembly 'Microsoft.Build' che a' Microsoft.Build.Framework' per far funzionare questo codice. – Sam

+0

Assicurati di controllare il valore di ritorno di 'Build' per vedere se ha avuto successo o meno. – Sam

+0

Per monitorare gli eventi di compilazione, utilizzare 'ConfigurableForwardingLogger' e impostare' BuildEventRedirector' su un 'IEventRedirector' personalizzato. È possibile verificare gli errori controllando che 'buildEvent' sia un' BuildErrorEventArgs'. – Sam

1

È necessario utilizzare SqlPackage.exe per pubblicare il proprio dacpac.

SqlPackage.exe 
    /Action:Publish 
    /SourceFile:C:/file.dacpac 
    /TargetConnectionString:[Connection string] 

Inoltre, invece di passare troppi parametri è possibile salvare le impostazioni in DAC profilo di pubblicazione (questo può essere fatto da Visual Studio)

+1

'should' ... dovrebbe essere' could' :) – ppumkin

19

che dovevo fare qualcosa di simile a questo perché VSDBCMD che abbiamo precedentemente usato non viene distribuito a SQL Server 2012 e abbiamo dovuto supportarlo. Quello che ho trovato è stato l'assembly Microsoft.SqlServer.Dac che sembra venire come parte degli strumenti di dati di SQL Server (http://msdn.microsoft.com/en-us/data/tools.aspx)

Quando si esegue questo sul computer client è necessaria la versione completa del framework .NET 4. e le tipologie di SQL CLR e SQL T-SQL ScriptDOM confezione trovate qui: http://www.microsoft.com/en-us/download/details.aspx?id=29065

codice di seguito è da un mockup che ho fatto per testare il nuovo metodo di distribuzione e distribuisce un dato file .dacpac

using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using Microsoft.SqlServer.Dac; 
    using System.IO; 

    namespace ConsoleApplication3 
    { 
     class Program 
     { 
      private static TextWriter output = new StreamWriter("output.txt", false); 
      static void Main(string[] args) 
      { 

       Console.Write("Connection String:"); 
       //Class responsible for the deployment. (Connection string supplied by console input for now) 
       DacServices dbServices = new DacServices(Console.ReadLine()); 

       //Wire up events for Deploy messages and for task progress (For less verbose output, don't subscribe to Message Event (handy for debugging perhaps?) 
       dbServices.Message += new EventHandler<DacMessageEventArgs>(dbServices_Message); 
       dbServices.ProgressChanged += new EventHandler<DacProgressEventArgs>(dbServices_ProgressChanged); 


       //This Snapshot should be created by our build process using MSDeploy 
       Console.WriteLine("Snapshot Path:"); 

       DacPackage dbPackage = DacPackage.Load(Console.ReadLine()); 




       DacDeployOptions dbDeployOptions = new DacDeployOptions(); 
       //Cut out a lot of options here for configuring deployment, but are all part of DacDeployOptions 
       dbDeployOptions.SqlCommandVariableValues.Add("debug", "false"); 


       dbServices.Deploy(dbPackage, "trunk", true, dbDeployOptions); 
       output.Close(); 

      } 

      static void dbServices_Message(object sender, DacMessageEventArgs e) 
      { 
       output.WriteLine("DAC Message: {0}", e.Message); 
      } 

      static void dbServices_ProgressChanged(object sender, DacProgressEventArgs e) 
      { 
       output.WriteLine(e.Status + ": " + e.Message); 
      } 
     } 
    } 

Questo sembra lavorare su tutte le versioni di SQL Server dal 2005 in poi. Esiste un insieme simile di oggetti disponibili in Microsoft.SqlServer.Management.Dac, tuttavia credo che questo sia nella versione precedente di DACFx e non è incluso nell'ultima versione. Quindi, se possibile, usa l'ultima versione.

+1

Brillante, l'utilizzo degli assembly DACPAC mi consente di assumere il pieno controllo della distribuzione. Utile anche per i test di integrazione! – Raffaeu

+0

Infine, una risposta sensata! Grazie - Voglio solo aggiungere che è necessario copiare/fare riferimento a 'sqlserver.dac.dll' da' Microsoft Visual Studio ??. 0 \ Common7 \ IDE \ Extensions \ Microsoft \ SQLDB \ DAC \ 120' - Funziona davvero bene, esattamente quello di cui avevo bisogno, così semplice e veloce. Questo dovrebbe essere accettato! – ppumkin

+0

Qualche esperienza con l'impostazione del flag "upgradeExisting" su false? Ricevo un'eccezione che mi dice "Impossibile eseguire la distribuzione nel database esistente quando l'aggiornamento è stato disabilitato". Ma voglio che DacServices rimuova prima il database. Non funziona, anche se aggiungo opzioni con CreateNewDatabase = true – Peter

1

Volevo creare e pubblicare un database basato su un file sqlproj e registrare informazioni utili su console. Ecco a cosa sono arrivato:

using Microsoft.Build.Framework; 
using Microsoft.Build.Execution; 

public void UpdateSchema() { 
    var props = new Dictionary<string, string> { 
     { "UpdateDatabase", "True" }, 
     { "PublishScriptFileName", "schema-update.sql" }, 
     { "SqlPublishProfilePath", "path/to/publish.xml") } 
    }; 

    var projPath = "path/to/database.sqlproj"; 

    var result = BuildManager.DefaultBuildManager.Build(
     new BuildParameters { Loggers = new[] { new ConsoleLogger() } }, 
     new BuildRequestData(new ProjectInstance(projPath, props, null), new[] { "Publish" })); 

    if (result.OverallResult == BuildResultCode.Success) { 
     Console.WriteLine("Schema update succeeded!"); 
    } 
    else { 
     Console.ForegroundColor = ConsoleColor.Red; 
     Console.WriteLine("Schema update failed!"); 
     Console.ResetColor(); 
    } 
} 

private class ConsoleLogger : ILogger 
{ 
    public void Initialize(IEventSource eventSource) { 
     eventSource.ErrorRaised += (sender, e) => { 
      Console.ForegroundColor = ConsoleColor.Red; 
      Console.WriteLine(e.Message); 
      Console.ResetColor(); 
     }; 
     eventSource.MessageRaised += (sender, e) => { 
      if (e.Importance != MessageImportance.Low) 
       Console.WriteLine(e.Message); 
     }; 
    } 
    public void Shutdown() { } 
    public LoggerVerbosity Verbosity { get; set; } 
    public string Parameters { get; set; } 
} 

Questo è per .NET 4 e versioni successive. Assicurati di includere i riferimenti all'assembly a Microsoft.Build e Microsoft.Build.Framework.

Problemi correlati