在面向netcoreapp2.0的MSBuild任务中使用SqlClient遇平台不支持问题
我来帮你搞定这个问题——你遇到的System.Data.SqlClient is not supported on this platform错误,根源在于MSBuild加载自定义任务时,没正确识别到这个库的平台特定依赖。先理清楚你的场景,再给你几个可行的解决方案:
你的场景回顾
你写了一个参考Nat McMaster的MSBuild任务示例的自定义任务,引用了System.Data.SqlClient,用dotnet publish命令面向netcoreapp2.0框架发布后,通过MSBuild脚本运行时触发了上述错误。使用的构建引擎是:
Microsoft (R) Build Engine version 15.7.177.53362 for .NET Core
你的MSBuild项目文件内容如下:
<Project DefaultTargets="Build"> <UsingTask TaskName="TestTasks.TestSqlClient" AssemblyFile=".\Task\bin\Debug\netcoreapp2.0\publish\TestTask.dll" /> <Target Name="Build"> <TestSqlClient /> </Target> </Project>
发布目录bin\netcoreapp2.0\publish的文件结构显示,System.Data.SqlClient的平台特定程序集和原生文件(比如Windows下的sni.dll)都分类存放在runtimes子目录里。
问题出在哪?
在.NET Core 2.x版本中,System.Data.SqlClient是带有平台专属原生依赖的NuGet包,它的程序集和原生文件会按平台分类放在runtimes目录下。但MSBuild默认加载自定义任务时,只会从任务程序集所在的根目录查找依赖,不会自动读取TestTask.deps.json里的依赖解析规则,导致它找不到当前平台需要的特定版本程序集和原生组件,最终抛出平台不支持的错误。
解决方案
方案1:让MSBuild通过依赖文件加载(最推荐)
修改你的MSBuild项目文件,给UsingTask加上DepsFile属性,指定任务的依赖描述文件:
<Project DefaultTargets="Build"> <UsingTask TaskName="TestTasks.TestSqlClient" AssemblyFile=".\Task\bin\Debug\netcoreapp2.0\publish\TestTask.dll" DepsFile=".\Task\bin\Debug\netcoreapp2.0\publish\TestTask.deps.json" /> <Target Name="Build"> <TestSqlClient /> </Target> </Project>
这个属性会告诉MSBuild按照deps.json里的规则,自动去runtimes目录查找对应平台的System.Data.SqlClient程序集和原生依赖,完美解决跨平台的依赖加载问题。
方案2:手动复制平台依赖(应急方案)
如果你的MSBuild版本不支持DepsFile属性,可以手动把当前平台对应的依赖文件复制到发布根目录:
- 要是在Windows x64环境:
- 把
runtimes/win-x64/native/sni.dll复制到publish根目录 - 把
runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll复制到publish根目录(覆盖根目录原有的同名文件)
- 把
- 要是在Unix环境:
把runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll复制到publish根目录
不过这个方案需要针对不同平台手动操作,灵活性差,不适合跨平台场景。
方案3:升级.NET Core和MSBuild版本
考虑把项目升级到.NET Core 3.1或更高版本,同时使用对应版本的MSBuild。更高版本的.NET对System.Data.SqlClient的依赖加载逻辑做了优化,MSBuild对自定义任务的依赖解析支持也更完善,能从根源减少这类兼容性问题。
验证
修改完MSBuild项目文件后,重新运行构建命令,应该就能正常加载System.Data.SqlClient并执行任务了。
内容的提问来源于stack exchange,提问作者Ashkan Nourzadeh

