question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

SqlClient is not usable via transitive reference because build scripts are not transitive.

See original GitHub issue

The Microsoft.Data.SqlClient package, as of version 1.0.19189.1-Preview, carries MSBuild targets that need to run when building .NET Framework apps in order to copy sni.dll. However, these targets are not “transitive” which means if you reference SqlClient indirectly through a library, you don’t get those build targets and end up with errors.

It’s my understanding that this can be solved by using a buildTransitive/ folder instead of build/. See the NuGet spec on the subject for more info. This was released in NuGet 5.0, so it does mean the package will require NuGet 5.0 or higher if it uses this feature.

Users can work around this issue by adding a direct dependency to Microsoft.Data.SqlClient but this is not the standard or expected practice in projects using the modern <PackageReference> syntax, which we do support for .NET Framework packages.

Repro steps

Example repo: https://github.com/anurse/SqlClientNotTransitive

  1. Clone the repo
  2. dotnet restore
  3. dotnet run --project ./Consumer

Detailed steps (from scratch instead of using the repo)

  1. cd to some empty directory
  2. dotnet new sln
  3. dotnet new console --name Consumer
  4. dotnet sln add ./Consumer
  5. dotnet new classlib --name Library
  6. dotnet sln add ./Library
  7. Add a <PackageReference>to Microsoft.Data.SqlClient 1.0.19189.1-Preview in Library.
  8. Add a <ProjectReference> to Library in Consumer
  9. Change the Consumer.csproj to target net471
  10. Add Connector.cs to Library:
using System;
using Microsoft.Data.SqlClient;

namespace Library
{
    public static class Connector
    {
        public static void Connect()
        {
            var connection = new SqlConnection(@"Server=(localdb)\MSSQLLocalDB;Database=CacheTestDb;Trusted_Connection=True;");
            connection.Open();
        }
    }
}
  1. Change Program.cs in Consumer to:
using System;
using Library;

namespace Consumer
{
    class Program
    {
        static void Main(string[] args)
        {
            Connector.Connect();
        }
    }
}
  1. dotnet run --project ./Consumer

Expected Behavior

Connecting
Connected

This presumes the connection string above is valid for your environment. Even if it isn’t you should at least see a connection failure message instead of what you end up getting.

Actual Behavior

Connecting

Unhandled Exception: System.TypeInitializationException: The type initializer for 'Microsoft.Data.SqlClient.SNINativeMethodWrapper' threw an exception. ---> System.ComponentModel.Win32Exception: Failed to load C:\Code\anurse\SqlClientNotTransitive\Consumer\bin\Debug\net471\x64\SNI.dll
   at Microsoft.Data.SqlClient.SNINativeMethodWrapper..cctor()
   --- End of inner exception stack trace ---
   at Microsoft.Data.SqlClient.SNINativeMethodWrapper.UnmanagedIsTokenRestricted(IntPtr token, Boolean& isRestricted)
   at Microsoft.Data.Win32NativeMethods.IsTokenRestrictedWrapper(IntPtr token)
   at Microsoft.Data.ProviderBase.DbConnectionPoolIdentity.GetCurrent()
   at Microsoft.Data.ProviderBase.DbConnectionPoolGroup.GetConnectionPool(DbConnectionFactory connectionFactory)
   at Microsoft.Data.ProviderBase.DbConnectionFactory.GetConnectionPool(DbConnection owningObject, DbConnectionPoolGroup connectionPoolGroup)
   at Microsoft.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   at Microsoft.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at Microsoft.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)
   at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
   at Microsoft.Data.SqlClient.SqlConnection.Open()
   at Library.Connector.Connect()
   at Consumer.Program.Main(String[] args)

The build output from Consumer does indeed show no sni.dll:

> dir .\Consumer\bin\Debug\net472


    Directory: C:\Code\anurse\SqlClientNotTransitive\Consumer\bin\Debug\net471

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----         7/10/2019  1:24 PM           4608 Consumer.exe
-a----         7/10/2019  1:18 PM           4264 Consumer.exe.config
-a----         7/10/2019  1:24 PM            468 Consumer.pdb
-a----         7/10/2019  1:24 PM           4096 Library.dll
-a----         7/10/2019  1:24 PM            524 Library.pdb
-a----          7/8/2019  4:59 PM        1880016 Microsoft.Data.SqlClient.dll
-a----        12/11/2017 10:10 AM         146616 System.Data.Common.dll
-a----        12/11/2017 10:10 AM          23264 System.Diagnostics.StackTrace.dll
-a----        12/11/2017 10:10 AM          31448 System.Diagnostics.Tracing.dll
-a----        12/11/2017 10:10 AM          24296 System.Globalization.Extensions.dll
-a----        12/11/2017 10:10 AM         110784 System.IO.Compression.dll
-a----        12/11/2017 10:10 AM         198464 System.Net.Http.dll
-a----        12/11/2017 10:10 AM          23224 System.Net.Sockets.dll
-a----        12/11/2017 10:10 AM          26888 System.Runtime.Serialization.Primitives.dll
-a----        12/11/2017 10:10 AM          44816 System.Security.Cryptography.Algorithms.dll
-a----        12/11/2017 10:10 AM          22240 System.Security.SecureString.dll
-a----        12/11/2017 10:10 AM          25816 System.Threading.Overlapped.dll
-a----        12/11/2017 10:10 AM          22744 System.Xml.XPath.XDocument.dll

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:15 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
stevefoocommented, Dec 13, 2019

thank you. we will look into migrating to core then.

Sent: Thursday, December 12, 2019 at 6:02 PM From: “Cheena Malhotra” notifications@github.com To: dotnet/SqlClient SqlClient@noreply.github.com Cc: SteveFoo codefoo@mail.com, Mention mention@noreply.github.com Subject: Re: [dotnet/SqlClient] SqlClient is not usable via transitive reference because build scripts are not transitive. (#137)

@stevefoo

I verified this works in WPF .NET Core project and not with WPF .NET Framework, would recommend opening issue with WPF Team (dotnet/wpf).

Although they’re .NET Core, I’m sure they can answer better on how to get it working with WPF .NET Framework too! From our side, it doesn’t look like a limitation.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

1reaction
mfreimcommented, Nov 5, 2019

I did some more investigation and found that this has to do with PackageReferences set to PrivateAssets in the solution. If I disable this the issue goes away.

To reproduce, use the same steps as the original comment, except add a Directory.Build.props to the solution root with the following contents:

<Project>
  <ItemDefinitionGroup>
    <PackageReference>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
  </ItemDefinitionGroup>
</Project>

Result Could not load file or assembly ‘Microsoft.Data.SqlClient, Version=1.10.19275.1, Culture=neutral, PublicKeyToken=23ec7fc2d6eaa4a5’ or one of its dependencies. The system cannot find the file specified.

I see the specific “Failed to load sni.dll” error when I do this for some unit tests.

Note that there’s no build error here, this is a runtime error. As far as I can tell this setup with PrivateAssets should be supported. If helpful I can open a new issue since the reproduction steps are slightly different.

Read more comments on GitHub >

github_iconTop Results From Across the Web

1.0.0 Milestone
SqlClient is not usable via transitive reference with dotnet-sdk ... via transitive reference because build scripts are not transitive.
Read more >
How can I track down the source of a transitive dependency?
For example, no projects in my solution directly reference the package System.Data.SqlClient, but something is pulling it in transitively.
Read more >
Could not load file or assembly System.Data.SqlClient
Hello, I'm currently learning the ASP.NET Core-Web-API (.NET 6) system. I added a class-library (.NET Framework) (v4.8) as a DataAccessLayer ...
Read more >
Solving Transitive Dependency Issues in .NET Core
Transitive dependency issues can be hard to identify and solve. Here's my unscientific approach to fixing them.
Read more >
SqlClient troubleshooting guide - ADO.NET Provider for ...
SqlClient " library. In scenarios where a transitive (indirect) reference is made, this ".targets" file should be manually referenced to ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found