I recently had a several day fight with a run-time exception. I lost way too much time on this. It came on a deadline week too, of course. I hope this helps you save a lot of time.
I have a lot of notes and info. You’re probably looking for the exception details. The solution is at the bottom.
I’ve created an issue on the Service Fabric Github page .
I was happily putting off creating the Azure DevOps pipeline and right-clicking from Visual Studio to publish. This was working great. A co-worker got freed up to create the release of the pipeline for me (I am able to do it, but was just too busy). After the first deploy, I got a new run-time exception (see below). I learned that I shouldn’t put off the automation (build and release) till later. I should do it right away as Jeremy Likness suggests on the Azure DevOps Podcast .
It is important to note that the publishing in ADO .Net with the Visual Studio Build task (msbuild /t:packge) works with .Net Core 2.2. I haven’t checked the differences in output between msbuild and dotnet publish for the Microsoft.Data.SqlClient.dll
Service Fabric OnPremise - version 7.0.457.9590
.Net Core 3.1.2 (netcoreapp31)
Entity Framework Core 3.1.2
Azure DevOps 2019 OnPremise
2 Asp .Net Core 3.1.2 projects for a publisher/subscriber setup
#LoECDA I'm needing to run a .Net Core 3.1 WorkerService in Service Fabric. I haven't found any tutorials. I'm used to running Apis as StatelessServices.
— Kevin Logan (@alignedDev) February 19, 2020
Can you help find me an example to follow?
Visual Studio, right-click publish on the .sfproj worked great. The Azure DevOps pipeline release has this run-time exception.
Note: I’ve changed namespaces to K. to remove company specific details.
System.PlatformNotSupportedException: Microsoft.Data.SqlClient is not supported on this platform. at Microsoft.Data.SqlClient.SqlConnection..ctor(String connectionString) at Microsoft.
The exception stack trace.
An exception occurred while iterating over the results of a query for context type 'K.Infrastructure.KDbContext'. System.PlatformNotSupportedException: Microsoft.Data.SqlClient is not supported on this platform. at Microsoft.Data.SqlClient.SqlConnection..ctor(String connectionString) at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerConnection.CreateDbConnection() at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.get_DbConnection() at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.CreateCommand(RelationalCommandParameterObject parameterObject, Guid commandId, DbCommandMethod commandMethod) at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(DbContext _, Boolean result, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`…
Thankfully that exception message is really helpful and pointed me to Microsoft.Data.SqlClient.dll.
I noticed that the Microsoft.Data.SqlClient (version 1.0.19269.1) was different from the VS publish to the ADO publish.
The left image is (publish from VS) right is from ADO. Interesting that the dll sizes are different…. Right click > package in VS, has a 1,199 KB Microsoft.Data.SqlClient.dll
.Net Core 2.2 doesn’t have this issue in our other SF Apis
Nuget on my machine: These are all version 1.0.19269.1 that I found on my laptop.
I don’t understand what all those are, but I was thinking there’d be a netcoreapp3.1. Maybe it used the netstandard2.0 version? (let me know if you know)
dotnet publish
on the Api projects. That’s where I saw that the Microsoft.Data.SqlClient.dll was different.<Target Name="PostPublish" BeforeTargets="Publish">
<Exec Command="move $(PublishDir)\runtimes $(PublishDir)\bin" />
</Target>
Both call MS build, so it must be repeatable from my machine… Right?
In the ADO Build, Build solution **\Prepaid.KServiceFabric.sfproj step, advanced > MS Build architecture to x64 Build logs: ##[command]“C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\amd64\msbuild.exe” “D:\agent_work\108\s\Repo\Source\ServiceFabric\K.ServiceFabric.sfproj” /nologo /nr:false /t:“Clean” … /p:SolutionDir=“D:\agent_work\108\s\Repo\Source” /t:Package /p:platform=“x64” /p:configuration=“Release” /p:VisualStudioVersion=“16.0”
I couldn’t see VS’s direct call when I right-click. I guess they call msbuild inside of a sandbox. I tried Procman from the suggestion on StackOverflow , but I still couldn’t see it. I also turned build logging output to detailed.
I finally decided to go my own way. I know that dotnet publish
got the right dll. I also learned that I couldn’t use dotnet cli to create a
SF package
. I created a .bat file to have something to run locally quickly. Then I moved that .bat file into the Azure DevOps build and called that. In the future, I may split it back out into separate build tasks.
Here is my bat file. Notice the steps.
REM Package K for SF
@echo off
set rootDir=%1
Echo Root Directory is %rootDir%
set publishDir=%rootDir%sfPublish
Echo Publish Directory is %publishDir%
set sourceDir=%rootDir%Source
Echo Source Directory is %sourceDir%
set deployDir=%publishDir%\deploy
Echo Deploy Directory is %deployDir%
Echo Delete %publishDir%
RD /S /Q %publishDir%
Echo delete %sourceDir%\K\ServiceFabric\pkg\Release
RD /S /Q %sourceDir%\K\ServiceFabric\pkg\Release
Echo Dotnet core publish Provider
dotnet publish %sourceDir%\K\Provider\Api\K.Provider.Api.csproj --runtime win10-x64 -c Release --framework netcoreapp3.1 /p:SolutionDir=%sourceDir% --self-contained -o %publishDir%\Provider\
Echo Dotnet core publish Consumer
dotnet publish %sourceDir%\L\Consumer\ApiWorkerForSf\K.Consumer.ApiWorkerForSf.csproj --runtime win10-x64 -c Release --framework netcoreapp3.1 /p:SolutionDir=%sourceDir% --self-contained -o %publishDir%\Consumer\
Echo msbuild /t:Package .sfproj
REM full path to msbuild is needed for the build agent
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\amd64\msbuild.exe" %sourceDir%\K\ServiceFabric\K.ServiceFabric.sfproj /p:SolutionDir=%sourceDir% /t:Package /p:platform="x64" /p:configuration="Release"
Echo copy pkg from K\ServiceFabric\ to publish\SfPackage
ROBOCOPY /E %sourceDir%\K\ServiceFabric\pkg\Release %publishDir%\SfPackage
ROBOCOPY "%publishDir%\SfPackage" "%deployDir%\Release" ApplicationManifest.xml
Echo copy files from publish\Provider to deploy\SfPackage\
ROBOCOPY /E "%publishDir%\SfPackage\K.Provider.ServiceFabricPkg" "%deployDir%\Release\K.Provider.ServiceFabricPkg"
ROBOCOPY /E "%publishDir%\Provider" "%deployDir%\Release\K.Provider.ServiceFabricPkg\Code"
Echo copy files from publish\Consumer to deploy\SfPackage\
ROBOCOPY /E "%publishDir%\SfPackage\K.Consumer.ServiceFabricPkg" "%deployDir%\Release\K.Consumer.ServiceFabricPkg"
ROBOCOPY /E "%publishDir%\Provider" "%deployDir%\Release\K.Consumer.ServiceFabricPkg\Code"
Echo Copy SF files
ROBOCOPY /E "%sourceDir%\K\ServiceFabric\ApplicationPackageRoot" "%publishDir%\SfPackage\ApplicationPackageRoot
ROBOCOPY /E "%sourceDir%\K\ServiceFabric\ApplicationParameters" "%publishDir%\SfPackage\ApplicationParameters
ROBOCOPY /E "%sourceDir%\K\ServiceFabric\PublishProfiles" "%publishDir%\SfPackage\PublishProfiles
Echo Copy Deploy Script
ROBOCOPY "%sourceDir%\K\ServiceFabric\Scripts" "%publishDir%" Deploy-FabricApplication.ps1
REM result we want in deploy/ is a release folder in the root that has sf packages, with dotnet publish dlls
REM applicationManifest.xml at the root
REM 2 ServiceFabricPkg/Code and /Config with ServiceManifest.xml
Here’s what it looks like in the ADO build. We have an intermediate CI build that makes that package. That gets picked up by the release that uses the built in SF task steps.
Path: $(RepoPath)\Build\createSfPackage.bat
Arguments: $(RepoPath)\
Zip: Script Path: $(Build.SourcesDirectory)\PowerShell\Zip.ps1
Arguments: -FolderToZip "$(RepoPath)\SfPublish\deploy\" -DestinationPath "$(SfPackageStagingPath)/PRS" -DestinationFileName "PRS-$(Version).zip"
The good news is that now I have a good story about how a container would have helped me. I’d also like to put my same code into Kubernetes, but the organization isn’t ready for that big of a change. I have a lot to learn about that approach as well.
Hopefully you won’t run into this or Microsoft will be able to fix the SF packaging so we won’t need this work around.
Please consider using Brave and adding me to your BAT payment ledger. Then you won't have to see ads! (when I get to $100 in Google Ads for a payout, I pledge to turn off ads)
Also check out my Resources Page for referrals that would help me.