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
#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 publishon 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 **\CHR.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.
Zip: Script Path:
-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 payment ledger. Then you won't have to see ads!