DacServices.Deploy 到 SQL 服务器 LocalDB 2016 失败 - 无法连接

DacServices.Deploy to SQL Server LocalDB 2016 failing - unable to connect

DacServices.Deploy 的调用在 SQL Server LocalDB 2014 上运行良好,但在安装 SQL Server LocalDB 2016 时失败:

string dacConnectionString = $"Server=(localdb)\mssqllocaldb; Integrated Security=true; database={DatabaseName}";
var dacServices = new DacServices(dacConnectionString);
dacServices.Message += (sender, args) => Console.WriteLine($"{args.Message.Prefix}: {args.Message.Message}"); // Log dacpac deploy messages
dacServices.Deploy(LoadDacPac(), DatabaseName, true, new DacDeployOptions()
                                                     {
                                                         BlockOnPossibleDataLoss = false
                                                     });

LocalDB 2016 DacServices.Deploy抛出的异常是:

Microsoft.SqlServer.Dac.DacServicesException was unhandled by user code
  HResult=-2146233088
  Message=Could not deploy package.
  Source=Microsoft.SqlServer.Dac
  StackTrace:
       at Microsoft.SqlServer.Dac.DeployOperation.Microsoft.SqlServer.Dac.IOperation.Run(OperationContext context)
       at Microsoft.SqlServer.Dac.OperationExtension.Execute(IOperation operation, DacLoggingContext loggingContext, CancellationToken cancellationToken)
       at Microsoft.SqlServer.Dac.DacServices.InternalDeploy(IPackageSource packageSource, Boolean isDacpac, String targetDatabaseName, DacDeployOptions options, CancellationToken cancellationToken, DacLoggingContext loggingContext)
       at Microsoft.SqlServer.Dac.DacServices.Deploy(DacPackage package, String targetDatabaseName, Boolean upgradeExisting, DacDeployOptions options, Nullable`1 cancellationToken)
       at Tv.Base.Test.Database.TestSqlLocalDb.CreateOrUpdateDatabaseIfNeeded(Boolean force) in D:\BuildAgent-02\workec37398501798d0\src\Base.Test.Database\TestSqlLocalDb.cs:line 173
       at Tv.Services.Inventory.DataAccess.Tests.InventoryDatabaseFixture..ctor() in C:\src\tv\services\inventory\test\DataAccess.Tests\InventoryDatabaseFixture.cs:line 40
  InnerException: 
       HResult=-2146233088
       Message=Unable to connect to target server.
       Source=Microsoft.Data.Tools.Schema.Sql
       StackTrace:
            at Microsoft.Data.Tools.Schema.Sql.Deployment.SqlDeploymentEndpointServer.OnInit(ErrorManager errors, String targetDBName)
            at Microsoft.Data.Tools.Schema.Sql.Deployment.SqlDeployment..ctor(SqlDeploymentConstructor constructor)
            at Microsoft.Data.Tools.Schema.Sql.Deployment.SqlDeploymentConstructor.ConstructServiceImplementation()
            at Microsoft.SqlServer.Dac.DacServices.CreatePackageToDatabaseDeployment(String connectionString, IPackageSource packageSource, String targetDatabaseName, DacDeployOptions options, ErrorManager errorManager)
            at Microsoft.SqlServer.Dac.DeployOperation.<>c__DisplayClass3.<>c__DisplayClass5.<CreatePlanInitializationOperation>b__1()
            at Microsoft.Data.Tools.Schema.Sql.Dac.OperationLogger.Capture(Action action)
            at Microsoft.SqlServer.Dac.DeployOperation.<>c__DisplayClass3.<CreatePlanInitializationOperation>b__0(Object operation, CancellationToken token)
            at Microsoft.SqlServer.Dac.Operation.Microsoft.SqlServer.Dac.IOperation.Run(OperationContext context)
            at Microsoft.SqlServer.Dac.ReportMessageOperation.Microsoft.SqlServer.Dac.IOperation.Run(OperationContext context)
            at Microsoft.SqlServer.Dac.OperationExtension.CompositeOperation.Microsoft.SqlServer.Dac.IOperation.Run(OperationContext context)
            at Microsoft.SqlServer.Dac.OperationExtension.CompositeOperation.Microsoft.SqlServer.Dac.IOperation.Run(OperationContext context)
            at Microsoft.SqlServer.Dac.DeployOperation.Microsoft.SqlServer.Dac.IOperation.Run(OperationContext context)

"unable to connect" 错误似乎 incorrect/may 掩盖了真正的错误,这既是因为指定的连接字符串允许我使用 SqlConnection 连接到数据库,也是因为我可以部署它dacpac 到 SQL 服务器 LocalDB 2016 使用命令行:

sqlpackage "/Action:publish" "/SourceFile:MyDatabase.dacpac" "/TargetConnectionString:Server=(localdb)\mssqllocaldb;Database=MyDatabase;Integrated Security=true"

关于我的设置的更多信息:

> sqllocaldb info mssqllocaldb
Name:               MSSQLLocalDB
Version:            13.0.1601.5
Shared name:
Owner:              DOMAIN\user
Auto-create:        Yes
State:              Running
Last start time:    7/1/2016 5:09:43 PM
Instance pipe name: np:\.\pipe\LOCALDB#C1DD8548\tsql\query

> sqllocaldb v
Microsoft SQL Server 2014 (12.0.2000.8)
Microsoft SQL Server 2016 (13.0.1601.5)

正在使用的 Microsoft.SqlServer.Dac 程序集来自这个 NuGet 包: https://www.nuget.org/packages/Microsoft.SqlServer.Dac

解决这个问题的方法确实是更新我们正在使用的 Microsoft.SqlServer.Dac 程序集的版本 - 我发现我应该在看到 @kevin-cunnane 的建议之前不久尝试一下。

有几个因素使它不那么明显,这就是它在 SO 上的原因:

  1. Dac 的错误消息 "Unable to connect to target server" 没有以任何方式表示版本不兼容。然而,从网上搜索(例如 )看来,除了不正确的连接字符串、防火墙问题等之外,此错误消息似乎还意味着版本不兼容。
  2. 发布了几个包含 Microsoft.SqlServer.Dac 和相关程序集的 NuGet 包。其中一些不是由 Microsoft 维护的,包括我正在使用的那个 (Microsoft.SqlServer.Dac). The official Microsoft release was not available on NuGet.org until June 2016, and it doesn't have the most obvious NuGet id (Microsoft.SqlServer.DacFx.x64)。所以运行update-package Microsoft.SqlServer.Dac没有达到预期的效果。
  3. "official" NuGet 包未在 MSDN + DAC 页面上的任何位置列出 - 您可能认为它会在此处提及:https://msdn.microsoft.com/en-us/library/dn702988%28v=sql.120%29.aspx - 但事实并非如此。
  4. Visual Studio 2016 安装 SQL LocalDB 2016,它 确实 包含正确的 Dac 程序集(C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\Extensions\Microsoft\SQLDB\DAC0\Microsoft.SqlServer.Dac.dll),但它们是未安装在 GAC 中或容易找到。

有效的修复是

# Remove the old NuGet dependencies
uninstall-package Microsoft.SqlServer.Dac

# Install the new Dac NuGet package
Install-Package Microsoft.SqlServer.DacFx.x64

Dac 团队的请求,如果你碰巧看到这个:

  • 请link从 MSDN 文档中选择正确的 NuGet 包
  • 请改进错误消息以指示需要更新的客户端软件
  • 请其他 NuGet 包维护者注意官方 NuGet 包的存在,或提供引用官方 NuGet 包的升级,b/c多个包的存在可能会引起焦虑。

(顺便说一句,尽管这里有困难,Dac/SSDT 是 AWESOME 。我还没有看到任何竞争性关系数据库的可比开发工具。)