问题描述
我的解决方案中有一个 sql Sever 数据库项目和几个依赖项项目。
当我编译(在 VS 中)这个数据库项目时,我得到了一个 sql 脚本和一个 .dacpac
文件。
但我也想将所有依赖项项目聚合到一个 dll 中,并仅为该结果 dll 创建 sql 脚本/.dacpac
文件。
我正在使用 ILMerge.MSBuild.Tasks.ILMerge 在 sqlproj 中的 AfterBuild 事件上聚合所有 dll。但是这种聚合发生在生成 sql 脚本之后。
构建日志:
2>------ Rebuild All started: Project: TestCLR,Configuration: Debug Any cpu ------
2> D:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Roslyn\csc.exe /noconfig /Nowarn:1701,1702,2008 /fullpaths /nostdlib+ /errorreport:prompt /warn:4 /define:DEBUG;TRACE /errorendlocation /preferreduilang:en-US /highentropyva+ /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\mscorlib.dll" /reference:D:\Work\FF\sql-Objects\Tools\TestCLR\bin\Debug\TestLogic.dll /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Data.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Xml.dll" /debug+ /debug:full /optimize- /out:obj\Debug\TestCLR.dll /subsystemversion:6.00 /target:library /warnaserror- /utf8output /langversion:7.3 TestProcedures.cs
2> Loading project references...
2> Loading project files...
2> Building the project model and resolving object interdependencies...
2> Validating the project model...
2> Writing model to D:\Work\FF\sql-Objects\Tools\TestCLR\obj\Debug\Model.xml...
2> Writing create script to TestCLR_Create.sql...
2> TestCLR -> D:\Work\FF\sql-Objects\Tools\TestCLR\bin\Debug\TestCLR.dll
2> TestCLR -> D:\Work\FF\sql-Objects\Tools\TestCLR\bin\Debug\TestCLR.dacpac
2> ILMerge bin\Debug\TestCLR.dll;bin\Debug\TestLogic.dll;bin\Debug\Sider.dll -> D:\Work\FF\sql-Objects\Tools\TestCLR\bin\Debug\TestCLR.dll
========== Rebuild All: 2 succeeded,0 Failed,0 skipped ==========
.sqlproj 部分与 ILMerge(现在它在最后一个位置。就在 /Project 标签之前)
<UsingTask TaskName="ILMerge.MSBuild.Tasks.ILMerge" AssemblyFile="$(SolutionDir)\packages\ILMerge.MSBuild.Tasks.1.0.0.3\tools\ILMerge.MSBuild.Tasks.dll" />
<Target Name="AfterBuild">
<ItemGroup>
<MergeAsm Include="bin\Debug\*.dll" />
</ItemGroup>
<PropertyGroup>
<MergedAssembly>$(ProjectDir)$(OutDir)RedisCLR.dll</MergedAssembly>
</PropertyGroup>
<Message Text="ILMerge @(MergeAsm) -> $(MergedAssembly)" Importance="high" />
<ILMerge InputAssemblies="@(MergeAsm)" OutputFile="$(MergedAssembly)" TargetKind="SameAsPrimaryAssembly" />
</Target>
非常感谢 Solomon Rutzky 先生。这个解决方案很有帮助。
<PropertyGroup>
<sqlBuildDependsOn>
BeforesqlBuild;
$(sqlBuildDependsOn);
</sqlBuildDependsOn>
</PropertyGroup>
<Target Name="BeforesqlBuild">
ILMerge things
</Target>
但是有一件奇怪的事情。 Dll 在流程结束时来到 Bin\debug (我认为在 PostBuildEvent 步骤或附近)。如果我将 ILMerge 移到流程的上层 - 它会返回错误,即没有 DLL。将 obj 文件夹和依赖项目中的配置更改为 gater dll。
解决方法
有趣的问题。我不知道有什么简单方法可以做到这一点,或者一开始是否有可能。但是,我知道有两个选项可以改变构建过程:
选项 1
注入构建步骤/目标。 SSDT 缺少至少两个构建步骤/目标——“BeforeSqlBuild”和“BeforePublish”——因为“AfterBuild”目标在过程中为时已晚(如您所见)。
为了解决 SQL Server 2017 中引入的“CLR 严格安全性”问题(记录在我的以下帖子中:SQLCLR vs. SQL Server 2017,Part 3: “CLR strict security” – Solution 2),我更新了 .sqlproj 文件,将紧跟在结束 </Project>
标记之前(使用证书签署程序集):
<PropertyGroup>
<SqlBuildDependsOn>
BeforeSqlBuild;
$(SqlBuildDependsOn);
</SqlBuildDependsOn>
</PropertyGroup>
<Target Name="BeforeSqlBuild">
<Exec Command="{DOS / Windows commands}"/>
</Target>
您可以保留 <Exec Command="..."/>
和/或添加现有“AfterBuild”目标的内容。但是,即使在正确的时间执行操作,我也不能完全确定您是否能够更改它想要序列化并放入“创建”脚本的程序集名称(即从使用“TestCLR .dll”到“RedisCLR.dll”)。您可以尝试重新分配构建变量,但我从未尝试过并且不确定是否允许。在这种情况下,下一个选项可能会有所帮助。
(请投票支持我的改进请求以改进 SSDT 构建过程:
Add MSBuild predefined Targets for "BeforeSqlBuild" and "BeforePublish" to SSDT SQL Server Database Projects)
选项 2
使用 .NET 创建可以访问对象、文件和整个过程的自定义构建任务: