5

I am calling a .net standard 2.0 library from a framework 4.7.2 test project sucessfully. references

If I take my .net standard 2.0 dll (SBD.Standard) and create a new winforms project that references it then I get asked to add

Microsoft.EntityFrameworkCore, 
then Microsoft.EntityFrameworkCore.SqlServer, 
then Microsoft.Data.SqlClient 

and then my project runs successfully. (Although it would be ideal if the extra packages were added automatically)

enter image description here

However trouble occurs if I try to distribute my library via a Nuget Package built using Azure DevOps.

However when I distribute the standard library via Nuget ( Using Azure DevOps to create the Nuget ) and include it in a new project I have an error.

The call stack is

System.IO.FileNotFoundException : Could not load file or assembly 'Microsoft.Data.SqlClient, Version=1.0.19269.1, Culture=neutral, PublicKeyToken=23ec7fc2d6eaa4a5' or one of its dependencies. The system cannot find the file specified.
   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.ExecuteReader(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.InitializeReader(DbContext _, Boolean result)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
   at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)
   at SBD.Standard.Helpers.HandyFuncs.QueueCommand(ApiDbContext connect, WorkTypeEnum workType, String 

The line of code that is causing the issue is

public static int QueueCommand(ApiDbContext connect, WorkTypeEnum workType, string description, int jobId, int signature, XElement elem)
{
    var command =
        connect.EngineCommandQueues.SingleOrDefault(
            c =>
                (c.Status == 0|| c.Status == 2) &&
                c.Signature == signature);

I did find that I needed to install the following packages

Microsoft.EntityFrameworkCore 3.1.1
Microsoft.EntityFrameworkCore.SqlServer 3.1.1 which has a dependency on Microsoft.Data.SqlClient >=1.019269.1

I see that Microsoft.Data.SQLClient v1.0.19269.1 is intalled

I tried installing System.Linq

I see the note in Nuget for Microsoft.Data.SqlClient

When running on Windows, this library has a dependency on Microsoft.Data.SqlClient.SNI on .NET Framework

and have Microsoft.Data.SqlClient.SNI v1.0.19235.1 installed

I tried upgrading Microsoft.Data.SqlClient to 1.1 and the error changed to

System.TypeInitializationException: The type initializer for 'Microsoft.Data.SqlClient.TdsParser' threw an exception. ---> System.TypeInitializationException: The type initializer for 'Microsoft.Data.SqlClient.SNILoadHandle' threw an exception. ---> System.TypeInitializationException: The type initializer for 'Microsoft.Data.SqlClient.SNINativeMethodWrapper' threw an exception. ---> System.ComponentModel.Win32Exception: Failed to load C:\Dev2\Combridge\SBD.ComBridge\UnitTestProjectStandard\bin\Debug\x86\SNI.dll ---> System.ComponentModel.Win32Exception: The specified module could not be found
    at Microsoft.Data.SqlClient.SNINativeMethodWrapper..cctor() in E:\agent1\_work\31\s\src\Microsoft.Data.SqlClient\netfx\src\Microsoft\Data\Interop\SNINativeMethodWrapper.cs:line 64
--- End of inner exception stack trace ---
    at Microsoft.Data.SqlClient.SNINativeMethodWrapper.SNIInitialize()
   at Microsoft.Data.SqlClient.SNILoadHandle..ctor() in E:\agent1\_work\31\s\src\Microsoft.Data.SqlClient\netfx\src\Microsoft\Data\SqlClient\TdsParserSafeHandles.cs:line 36
   at Microsoft.Data.SqlClient.SNILoadHandle..cctor() in E:\agent1\_work\31\s\src\Microsoft.Data.SqlClient\netfx\src\Microsoft\Data\SqlClient\TdsParserSafeHandles.cs:line 17
--- End of inner exception stack trace ---
    at Microsoft.Data.SqlClient.TdsParser..cctor() in E:\agent1\_work\31\s\src\Microsoft.Data.SqlClient\netfx\src\Microsoft\Data\SqlClient\TdsParser.cs:line 166
--- End of inner exception stack trace ---
    at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) in E:\agent1\_work\31\s\src\Microsoft.Data.SqlClient\netfx\src\Microsoft\Data\ProviderBase\DbConnectionPool.cs:line 1411
   at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) in E:\agent1\_work\31\s\src\Microsoft.Data.SqlClient\netfx\src\Microsoft\Data\ProviderBase\DbConnectionPool.cs:line 1310
   at Microsoft.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) in E:\agent1\_work\31\s\src\Microsoft.Data.SqlClient\netfx\src\Microsoft\Data\ProviderBase\DbConnectionFactory.cs:line 357
   at Microsoft.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) in E:\agent1\_work\31\s\src\Microsoft.Data.SqlClient\netfx\src\Microsoft\Data\ProviderBase\DbConnectionInternal.cs:line 773
   at Microsoft.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) in E:\agent1\_work\31\s\src\Microsoft.Data.SqlClient\netfx\src\Microsoft\Data\ProviderBase\DbConnectionClosed.cs:line 72
   at Microsoft.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry) in E:\agent1\_work\31\s\src\Microsoft.Data.SqlClient\netfx\src\Microsoft\Data\SqlClient\SqlConnection.cs:line 1860
   at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry) in E:\agent1\_work\31\s\src\Microsoft.Data.SqlClient\netfx\src\Microsoft\Data\SqlClient\SqlConnection.cs:line 1853
   at Microsoft.Data.SqlClient.SqlConnection.Open() in E:\agent1\_work\31\s\src\Microsoft.Data.SqlClient\netfx\src\Microsoft\Data\SqlClient\SqlConnection.cs:line 1421
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnection(Boolean errorsExpected)
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Open(Boolean errorsExpected)
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.InitializeReader(DbContext _, Boolean result)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
   at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)
   at lambda_method(Closure , QueryContext )
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
   at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)

[Update] Reading This GitHub post it seems it could have something to do with Azure Devops

The post mentions

Win32Exception: Failed to load C:__source_code\repo1\Simplified\bin\x86\SNI.dll So it's trying to load the 32 bit version of sni.dll and it isn't present.

That makes me suspect that you build it on a 64 bit system and then just transferred the files to the other machine. You need to publish the project for an x86 target to get the right native dependency resolved. Give it a try.

I am running Windows 10 so I dont see why it would be trying to load a 32 bit version of sni.dll

I can see in the Azure Artifiacts

Microsoft.Data.SqlClient.SNI 1.0.19235.1

[Update]

I see from this question that I need to force MSBuild to create / update a YourProject.dll.config file containing the necessary binding redirects. So Nuget should be creating that config file too. I wonder how that effects things.

My azure-pipelines.yml is

# .NET Desktop
# Build and run tests for .NET Desktop or Windows classic desktop solutions.
# Add steps that publish symbols, save build artifacts, and more:
# https://docs.microsoft.com/azure/devops/pipelines/apps/windows/dot-net

trigger:
- master

pool:
  vmImage: 'windows-latest'

variables:
  solution: '**/*.sln'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'
  Major: '2'
  Minor: '0'
  Patch: '0'

steps:
- task: NuGetToolInstaller@0
  inputs:
    versionSpec: '>=4.3.0'
    checkLatest: true

- task: NuGetCommand@2
  inputs:
    restoreSolution: '$(solution)'

- task: VSBuild@1
  inputs:
    solution: '$(solution)'
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'

- task: NuGetCommand@2
  inputs:
    command: pack
    packagesToPack: '**/*.csproj'
    versioningScheme: byPrereleaseNumber
    majorVersion: '$(Major)'
    minorVersion: '$(Minor)'
    patchVersion: '$(Patch)'

- task: NuGetCommand@2
  inputs:
    command: pack
    packagesToPack: '**/*.vbproj'
    versioningScheme: byPrereleaseNumber
    majorVersion: '$(Major)'
    minorVersion: '$(Minor)'
    patchVersion: '$(Patch)'

- task: NuGetCommand@2
  displayName: 'NuGet push'
  inputs:
    command: push
    publishVstsFeed: 'SBDCommonFeed'
    allowPackageConflicts: true

[Update]

I tried changing the yaml to use dotnet pack but get an error

error

[Update]

I tried replacing the pack section of the yaml with

- task: DotNetCoreCLI@2
  inputs:
    command: 'pack'
    selectOrConfig: 'config'
    nugetConfigPath: '$(System.DefaultWorkingDirectory)/NuGet.config'
    externalEndpoints: $(externalFeedCredential)

Now I get resource authorization issue Resource Authorization Issue

When I click the button to authorize I get a message: insufficient permissions or missing resources. Even though I am logged in as the repository owner.

I guess I need to learn what to put in externalEndpoints

[Update]

I tried this instead

- task: DotNetCoreCLI@2
  inputs: 
    command: 'pack'
    outputDir: '$(Build.ArtifactStagingDirectory)/TestDir'

Now the error becomes

 error MSB4057: The target "pack" does not exist in the project.

investigating this answer

Kirsten Greed
  • 11,170
  • 26
  • 117
  • 234
  • https://github.com/dotnet/runtime/issues/26543 – Kirsten Greed Feb 12 '20 at 00:54
  • https://github.com/Azure/app-service-announcements-discussions/issues/9#issuecomment-322922859 – Kirsten Greed Feb 12 '20 at 01:38
  • I am going to try adding system.data.sqlclient to my standard library – Kirsten Greed Feb 12 '20 at 01:40
  • https://github.com/dotnet/efcore/issues/19172 – Kirsten Greed Feb 12 '20 at 02:01
  • I was experiencing this issue. I wonder if it is related https://stackoverflow.com/questions/43995432/could-not-load-file-or-assembly-microsoft-extensions-dependencyinjection-abstrac – Kirsten Greed Feb 12 '20 at 04:11
  • 1
    When you developed the library project locally in VS, did the project references the three packages above? And if we create the nuget locally in VS(right-click project=>pack), and consume it in your another project, does it work all well? The error messages are a bit strange but since it works well when you `and then my project runs successfully`, it seems to me there should be something wrong with your `pack step` in Azure devops... Do you use dotnet pack command? – LoLance Feb 12 '20 at 04:16
  • I updated the top of the question to show the references I am using and added the yaml near the end of the question. @LanceLi-MSFT Investigating the pack idea. – Kirsten Greed Feb 12 '20 at 04:30
  • Hmm, you use nuget pack. And as I know, there's one open issue for `nuget pack` command in .net core/.net standard projects. See [here](https://github.com/NuGet/Home/issues/4491), I think you should use `dotnet pack`(.net core task in Azure Devops and choose pack option) to create nuget correct package. Then consume it in your another project, rebuild and make sure all referenced assemblies are in output folder. Then it would work well... – LoLance Feb 12 '20 at 04:43
  • If I create the Nuget pack locally it works. I will investigate your further suggestions – Kirsten Greed Feb 12 '20 at 04:47
  • @LanceLi-MSFT I updated the end of the question with my attempt to use dotnet pack it did not work. – Kirsten Greed Feb 12 '20 at 04:57
  • Not nuget related task, use [dotnet related task](https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/build/dotnet-core-cli?view=azure-devops). See [this](https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/build/dotnet-core-cli?view=azure-devops#pack). And it's recommended task if you're doing something with .net core/.net standard projects. See **Notes** in [Nuget Task](https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/package/nuget?view=azure-devops). – LoLance Feb 12 '20 at 05:00

3 Answers3

3

Although it would be ideal if the extra packages were added automatically.

Assuming we have one .net standard project which depends on Microsoft.EntityFrameworkCore, Microsoft.EntityFrameworkCore.SqlServer and other packages. The expected behavior for us is to create a nuget package in whose xx.nuspec file has definitions about the dependencies.

But there's one issue about nuget pack command, it can't work well for .net core/standard project. Both nuget pack and dotnet pack can create .net standard nuget packages successfully, but pack successfully doesn't mean good package.

With the effect of the issue above, package created by nuget pack will lose some dependencies in Package.nuspec file. (Rename xx.nupkg to xx.zip, then we can check the content inside package, we'll see the xx.nuspec file)

And above step can cause runtime error like missing assembly. So to make it ideal that the extra packages are added automatically and avoid missing reference, we recommend dotnet pack command for projects using PackageReference format. (No matter dotnet pack command locally or dotnet pack task in Azure Devops Piepilne)

LoLance
  • 18,434
  • 1
  • 12
  • 39
  • I have run into problems trying to get the whole repository published. I think because it contains framework and standard projects. I will ask a new question. – Kirsten Greed Feb 12 '20 at 05:32
  • https://stackoverflow.com/questions/60181799/can-i-mix-framework-projects-and-net-standard-projects-in-the-same-repository – Kirsten Greed Feb 12 '20 at 05:38
  • https://stackoverflow.com/questions/60197552/how-do-i-get-azure-devops-to-create-a-correct-nuspec-for-a-net-standard-2-0-pro – Kirsten Greed Feb 12 '20 at 22:03
1

just hit the same error with ASP.NET 4.7.2 (updated from net 4.6) project which reference netstandard 2.0 project (ef core 3.x). (on azure app service)

after trying to clean/rebuild/nuget reinstall .. i removed everything from app service and published project again. error dismissed.

ish1313
  • 161
  • 1
  • 6
0

I re-experienced this recently and could not solve with the above method. I decided to separate the .netstandard2.0 projects from the net472 projects into different Azure projects.

Investigating ...

Kirsten Greed
  • 11,170
  • 26
  • 117
  • 234