我需要在使用WIX安装数据库时部署dacpac。为此,我考虑使用必要的开关运行SQLPackage.exe命令,所以我使用二进制标签嵌入了必要的exe和dll,如下所示
<Binary Id="Microsoft.Data.Tools.Schema.Sql.dll" SourceFile="..\DeployDBs\DAC\Microsoft.Data.Tools.Schema.Sql.dll"/>
<Binary Id="Microsoft.Data.Tools.Schema.Tasks.Sql.11.dll" SourceFile="..\DeployDBs\DAC\Microsoft.Data.Tools.Schema.Tasks.Sql.11.dll"/>
<Binary Id="Microsoft.Data.Tools.Schema.Utilities.Sql.11.dll" SourceFile="..\DeployDBs\DAC\Microsoft.Data.Tools.Schema.Utilities.Sql.11.dll"/>
<Binary Id="Microsoft.Data.Tools.Utilities.dll" SourceFile="..\DeployDBs\DAC\Microsoft.Data.Tools.Utilities.dll"/>
<Binary Id="Microsoft.SqlServer.Dac.dll" SourceFile="..\DeployDBs\DAC\Microsoft.SqlServer.Dac.dll"/>
<Binary Id="SqlPackage" SourceFile="..\DeployDBs\DAC\SqlPackage.exe"/>
<Binary Id="SqlPackage.exe.config" SourceFile="..\DeployDBs\DAC\SqlPackage.exe.config"/>
使用自定义操作调用SqlPackage.exe,如下所示
<CustomAction Id="DeployMyDb" BinaryKey="SqlPackage"
ExeCommand="/a:publish /sf:"MyDacpac.dacpac" /tsn:localhost /tdn:MyDb"
Execute="immediate" />
自定义操作是在&#39; InstallFinalize&#39;之后运行的序列。如下
<InstallExecuteSequence>
<Custom Action="DeployMyDb" After="InstallFinalize"/>
</InstallExecuteSequence>
</Product>
当部署dacpac时(即运行自定义操作),它会抛出&#39; FileNotFoundException&#39;对于汇编&#39; Microsoft.Data.Tools.Utilities,它是嵌入式二进制文件之一。
请告知缺少的步骤或添加要运行此exe所需的内容。
答案 0 :(得分:3)
我找到了解决方案。
我没有采用上述方法,而是为自定义操作创建了一个单独的项目,并添加了对所需二进制文件的引用(即我之前在&lt; binary&gt;标记中提到的二进制文件)并添加了二进制标记中形成的相应dll并调用了通过&lt; CustomAction&gt;
所得溶液如下:
<Binary Id="InstallerWix_CustomAction.CA.dll" SourceFile="..\InstallerWix_CustomAction\bin\Debug\InstallerWix_CustomAction.CA.dll" />
<CustomAction Id="DeployDb" BinaryKey="InstallerWix_CustomAction.CA.dll"
DllEntry="CustomAction1"
Execute="immediate" Return="check" />
<InstallExecuteSequence>
<Custom Action="DeployDb" After="InstallFinalize"/>
</InstallExecuteSequence>
答案 1 :(得分:2)
我能够通过将dacpac文件添加为二进制文件,在CustomAction中读取该二进制文件,最后在我的C#自定义操作中使用'Microsoft.SqlServer.Dac'(在nuget上可用)来实现此功能。
我必须将二进制文件流写入MemoryStream以与DacPac.Load函数一起使用。二进制流是内部类型的“RecordStream”,Load函数无法使用它。出于您的目的,您可能还需要修改dacOptions变量以获得所需的结果。
请参阅下面的示例:
Project.wxs:
<Binary Id="Database.dacpac" SourceFile="$(var.ProjectDir)\Database.dacpac" />
<CustomAction Id="DeployDacpac" BinaryKey="CustomAction.dll" DllEntry="DeployDacpac" Execute="immediate" />
<InstallExecuteSequence>
<Custom Action="DeployDacpac" After="InstallFinalize" />
</InstallExecuteSequence>
CustomAction.cs:
[CustomAction]
public static ActionResult DeployDacpac(Session session)
{
try
{
string sql = string.Format("SELECT Data FROM Binary WHERE Name = 'Database.dacpac'");
View view = session.Database.OpenView(sql);
view.Execute();
var dataStream = view.First()["Data"] as Stream;
byte[] buffer = new byte[dataStream.Length];
int bytesRead;
while ((bytesRead = dataStream.Read(buffer, 0, buffer.Length)) > 0) ;
using (MemoryStream ms = new MemoryStream(buffer))
{
var dacOptions = new DacDeployOptions();
dacOptions.BlockOnPossibleDataLoss = false;
dacOptions.DropDmlTriggersNotInSource = false;
dacOptions.DropObjectsNotInSource = false;
var dacServiceInstance = new DacServices(GenerateConnectionString(session["SQLSERVER"], session["SQLDATABASE"], session["SQLUSER"], session["SQLPASSWORD"]));
using (DacPackage dacpac = DacPackage.Load(ms))
{
dacServiceInstance.Deploy(dacpac, session["SQLDATABASE"], upgradeExisting: true, options: dacOptions);
}
}
}
catch (Exception ex)
{
session.Log(ex.Message);
return ActionResult.Failure;
}
return ActionResult.Success;
}