SqlClient: PlatformNotSupportedException on Locally executing function app.

Describe the bug

Upon invoking the SqlConnection(“connection string”) constructor in an Azure Function running in .net core 22 I get System.PlatformNotSupportedException: 'Microsoft.Data.SqlClient is not supported on this platform.'

System.PlatformNotSupportedException
  HResult=0x80131539
  Message=Microsoft.Data.SqlClient is not supported on this platform.
  Source=Microsoft.Data.SqlClient
  StackTrace:
   at Microsoft.Data.SqlClient.SqlConnection..ctor(String connectionString)
   at FunctionApp2.Function1.<Run>d__4.MoveNext() in C:\Users\Justin Dearing\source\repos\FunctionApp2\FunctionApp2\Function1.cs:line 38

Before that exception I get System.IO.FileNotFoundException:

System.IO.FileNotFoundException
  HResult=0x80070002
  Message=Could not load file or assembly 'Microsoft.Data.SqlClient, Version=1.0.19128.1, Culture=neutral, PublicKeyToken=23ec7fc2d6eaa4a5'. The system cannot find the file specified.
  Source=System.Private.CoreLib
  StackTrace:
   at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, IntPtr ptrLoadContextBinder)
   at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, IntPtr ptrLoadContextBinder)
   at System.Reflection.Assembly.Load(AssemblyName assemblyRef, IntPtr ptrLoadContextBinder)
   at System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyName(AssemblyName assemblyName)
   at Microsoft.Azure.WebJobs.Script.Description.FunctionAssemblyLoadContext.TryLoadRuntimeAssembly(AssemblyName assemblyName, Assembly& assembly) in C:\azure-webjobs-sdk-script\src\WebJobs.Script\Description\DotNet\FunctionAssemblyLoadContext.cs:line 235

The exception is thrown in the azure function runtime FunctionAssemblyLoadContext.TryLoadRuntimeAssembly() line 235

Using procmon.exe, its definitely finding the file. image

To reproduce

Include a complete code listing (or project/solution) that we can run to reproduce the issue.

Partial code listings, or multiple fragments of code, will slow down our response or cause us to push the issue back to you to provide code to reproduce the issue.

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.Services.AppAuthentication;
using System.Text;

namespace FunctionApp2
{
    public static class Function1
    {
        private const string ConnectionStringKey = "SqlConnectionString";
        private const string SqlTokenTenantKey = "SqlTenant";
        private const string AzureSqlDbResource = "https://database.windows.net/";

        private static string ConnectionString =>
            Environment.GetEnvironmentVariable(ConnectionStringKey, EnvironmentVariableTarget.Process);

        private static string SqlTokenTenant =>
            Environment.GetEnvironmentVariable(SqlTokenTenantKey, EnvironmentVariableTarget.Process);

        private static async Task<string> GetAccessTokenAsync()
        {
            var azureServiceTokenProvider = new AzureServiceTokenProvider();
            return await azureServiceTokenProvider.GetAccessTokenAsync(AzureSqlDbResource, SqlTokenTenant);
        }

        [FunctionName("Function1")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            var sb = new StringBuilder();
            log.LogTrace("Creating Database connection object.");
            //using (var cn = new System.Data.SqlClient.SqlConnection(ConnectionString))
            using (var cn = new Microsoft.Data.SqlClient.SqlConnection(ConnectionString))
            {
                log.LogTrace("Accquiring Access Token", cn.AccessToken);
                cn.AccessToken = await GetAccessTokenAsync();
                log.LogTrace("Accquired Access Token {token}", cn.AccessToken);
                using (var cmd = cn.CreateCommand())
                {
                    cn.Open();
                    cmd.CommandText = "SELECT * FROM sys.tables";
                    using (var sqlRdr = cmd.ExecuteReader())
                    while (sqlRdr.Read())
                    {
                            for (var i= 0; i < sqlRdr.FieldCount; i++)
                            {
                                sb.AppendFormat("{0},", sqlRdr[i]);
                            }
                            sb.AppendLine();
                        }
                    cn.Close();
                }
            }

            var result = new ContentResult();
            result.Content = sb.ToString();
            return result;
        }
    }
}
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <AzureFunctionsVersion>v2</AzureFunctionsVersion>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Dapper" Version="1.60.6" />
    <PackageReference Include="FlatFiles" Version="4.5.0" />
    <PackageReference Include="Microsoft.Azure.Services.AppAuthentication" Version="1.0.3" />
    <PackageReference Include="Microsoft.Data.SqlClient" Version="1.0.19128.1-Preview" />
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.28" />
    <PackageReference Include="System.Data.SqlClient" Version="4.6.1" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
</Project>

Expected behavior

I expect to instantiate the sqlconnection object.

Further technical details

Microsoft.Data.SqlClient version: 1.0.19128.1-Preview .NET target: Core 2.2 SQL Server version: Azure v12 Operating system: Windows 10.0.17134.765 Azure Function Tools: 2.22.0 Azure Functions Core Tools (2.7.1158 Commit hash: f2d2a2816e038165826c7409c6d10c0527e8955b) Function Runtime Version: 2.0.12438.0

Additional context

Created the project in VS 2017 and moved it to 2019.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 16 (4 by maintainers)

Most upvoted comments

Hi @zippy1981,

This looks like the issue is stemming from how Azure Functions doesn’t copy the dll to the output directory, details of which can be found here: issue #4304. They’ve suggested a “workaround” for which the discussion is still ongoing. I’ve added the below snippet to my .csproj and saw that the error is no longer reproducible in my local Azure function app environment. Could you try the same and let me know if this solves your issue / is an acceptable solution? Thanks.

  <ItemGroup>
    <None Include="$(USERPROFILE)\.nuget\packages\microsoft.data.sqlclient\1.0.19189.1-preview\runtimes\win\lib\netcoreapp2.1\Microsoft.Data.SqlClient.dll">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
  </ItemGroup>

  <Target Name="CopyToBin" BeforeTargets="Build">
    <Copy SourceFiles="$(USERPROFILE)\.nuget\packages\microsoft.data.sqlclient\1.0.19189.1-preview\runtimes\win\lib\netcoreapp2.1\Microsoft.Data.SqlClient.dll" DestinationFolder="$(OutputPath)\bin" />
  </Target>