使用Microsoft.Build.Evaluation来发布数据库项目(.sqlproj)

14
我需要能够以编程方式发布SSDT项目。我正在考虑使用Microsoft.Build来实现,但找不到任何文档。创建 .dacpac 似乎非常简单,但我应该如何发布到现有数据库,或者至少发布到一个 .sql 文件中?我的想法是让它执行右键单击项目并选择“发布”时所做的操作。它应该与选定的数据库进行比较并生成升级脚本。
下面是我目前用于创建 .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());

  }
}

本质上我正在尝试实现这个MSBuild示例所展示的内容,但是希望在代码中完成。

很抱歉这就是我所拥有的全部了。对于Build类的文档非常不完整,任何帮助将不胜感激。

谢谢。

4个回答

20

我之前必须做类似的事情,因为我们以前使用的VSDBCMD不支持部署到SQL Server 2012,而我们需要支持它。我发现了Microsoft.SqlServer.Dac程序集,它似乎是作为SQL Server数据工具的一部分提供的(http://msdn.microsoft.com/en-us/data/tools.aspx)。

当您在客户机上运行此程序时,您将需要完整版本的.NET 4框架,以及SQL CLR类型和SQL T-SQL ScriptDOM包,可以在此处找到:http://www.microsoft.com/en-us/download/details.aspx?id=29065

下面的代码来自我为测试新部署方法制作的模型,并且可以部署给定的.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);
            }
        }
    }

这似乎适用于所有版本的SQL Server,从2005年以来。在Microsoft.SqlServer.Management.Dac中有一组类似的对象可用,但我认为这是在先前版本的DACFx中,并未包含在最新版本中。因此,如果可以,请使用最新版本。


1
太棒了,使用DACPAC程序集使我可以完全控制部署。对于集成测试也非常有用! - Raffaeu
终于有一个明智的回答!谢谢 - 只想补充一下,您需要从 Microsoft Visual Studio ??.0\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\120 复制/引用 sqlserver.dac.dll - 运行得非常好,正是我所需要的,如此简单和快速。这应该被接受! - Piotr Kula
有没有使用“upgradeExisting”标志设置为false的经验?我收到一个异常告诉我“当禁用升级时无法部署到现有数据库”。但是我想让DacServices首先删除数据库。即使我添加了CreateNewDatabase = true选项,它也不起作用。 - Peter
@Peter - 有一个重载函数可以升级现有的服务: services.Deploy(package, connectionString, upgradeExisting: true); - Dave Mateer

3

我们需要一种方法来告诉msbuild如何在哪里发布。在Visual Studio中打开您的项目并开始将其发布。在对话框中输入所有必要的信息,包括您的数据库连接信息和任何自定义SQLCMD变量值。另存为配置文件...保存到一个文件中,例如Northwind.publish.xml。(然后您可以选择取消。)现在我们可以使用此文件和项目文件来构建和发布:

// 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});

这可能需要一些时间,看起来可能会卡住。请耐心等待。 :)


1
我需要引用Microsoft.BuildMicrosoft.Build.Framework两个程序集才能使这段代码正常运行。 - Sam
请务必检查 Build 的返回值,以查看是否成功。 - Sam
要监视构建事件,请使用ConfigurableForwardingLogger并将BuildEventRedirector设置为自定义的IEventRedirector。您可以通过检查buildEvent是否为BuildErrorEventArgs来检查错误。 - Sam
如果您想一直发布到一个数据库,那也没关系,但是DAC似乎允许我针对任何服务器或数据库进行定位,因此我可以根据DACPAC需要创建和删除数据库。 - Piotr Kula

1
我希望构建并发布一个基于sqlproj文件的数据库,并将有用的信息记录到控制台。以下是我得出的结果:
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; }
}

这是针对 .NET 4 及以上版本的。请确保包含对 Microsoft.BuildMicrosoft.Build.Framework 的程序集引用。

1

您应该使用SqlPackage.exe来发布您的dacpac。

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

另外,你可以将设置保存到 DAC 发布配置文件中,而不是传递太多的参数(这可以从 Visual Studio 中完成)。


1
应该是 could :) - Piotr Kula

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接