解决方案 假设我们有一个 .net standard 项目,它依赖于 Microsoft.EntityFrameworkCore、Microsoft.EntityFrameworkCore.SqlServer 和其他包.我们的预期行为是创建一个 nuget 包,其 xx.nuspec 文件中包含有关 依赖项.但是有关于 nuget pack 命令的一个问题,它不能很好地用于 .net core/standard 项目.nuget pack 和dotnet pack 都可以成功创建.net standard nuget 包,但pack successfully 并不意味着好包.受上述问题的影响,nuget pack创建的包会丢失Package.nuspec文件中的一些依赖.(将 xx.nupkg 重命名为 xx.zip,然后我们可以查看包内的内容,我们会看到 xx.nuspec 文件)以上步骤可能会导致运行时错误,例如缺少程序集.因此,为了使额外的包自动添加并避免丢失引用,我们建议对使用 PackageReference 格式的项目使用 dotnet pack 命令.(无论是本地的 dotnet pack 命令还是 Azure Devops Piepilne 中的 dotnet pack 任务)I am calling a .net standard 2.0 library from a framework 4.7.2 test project sucessfully.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.SqlClientand then my project runs successfully. (Although it would be ideal if the extra packages were added automatically)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 isSystem.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, StringThe 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 packagesMicrosoft.EntityFrameworkCore 3.1.1Microsoft.EntityFrameworkCore.SqlServer 3.1.1 which has a dependency on Microsoft.Data.SqlClient >=1.019269.1I see that Microsoft.Data.SQLClient v1.0.19269.1 is intalledI tried installing System.LinqI see the note in Nuget for Microsoft.Data.SqlClientand have Microsoft.Data.SqlClient.SNI v1.0.19235.1 installedI 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:Dev2CombridgeSBD.ComBridgeUnitTestProjectStandardinDebugx86SNI.dll ---> System.ComponentModel.Win32Exception: The specified module could not be found at Microsoft.Data.SqlClient.SNINativeMethodWrapper..cctor() in E:agent1\_work31ssrcMicrosoft.Data.SqlClientetfxsrcMicrosoftDataInteropSNINativeMethodWrapper.cs:line 64--- End of inner exception stack trace --- at Microsoft.Data.SqlClient.SNINativeMethodWrapper.SNIInitialize() at Microsoft.Data.SqlClient.SNILoadHandle..ctor() in E:agent1\_work31ssrcMicrosoft.Data.SqlClientetfxsrcMicrosoftDataSqlClientTdsParserSafeHandles.cs:line 36 at Microsoft.Data.SqlClient.SNILoadHandle..cctor() in E:agent1\_work31ssrcMicrosoft.Data.SqlClientetfxsrcMicrosoftDataSqlClientTdsParserSafeHandles.cs:line 17--- End of inner exception stack trace --- at Microsoft.Data.SqlClient.TdsParser..cctor() in E:agent1\_work31ssrcMicrosoft.Data.SqlClientetfxsrcMicrosoftDataSqlClientTdsParser.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\_work31ssrcMicrosoft.Data.SqlClientetfxsrcMicrosoftDataProviderBaseDbConnectionPool.cs:line 1411 at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) in E:agent1\_work31ssrcMicrosoft.Data.SqlClientetfxsrcMicrosoftDataProviderBaseDbConnectionPool.cs:line 1310 at Microsoft.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) in E:agent1\_work31ssrcMicrosoft.Data.SqlClientetfxsrcMicrosoftDataProviderBaseDbConnectionFactory.cs:line 357 at Microsoft.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) in E:agent1\_work31ssrcMicrosoft.Data.SqlClientetfxsrcMicrosoftDataProviderBaseDbConnectionInternal.cs:line 773 at Microsoft.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) in E:agent1\_work31ssrcMicrosoft.Data.SqlClientetfxsrcMicrosoftDataProviderBaseDbConnectionClosed.cs:line 72 at Microsoft.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry) in E:agent1\_work31ssrcMicrosoft.Data.SqlClientetfxsrcMicrosoftDataSqlClientSqlConnection.cs:line 1860 at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry) in E:agent1\_work31ssrcMicrosoft.Data.SqlClientetfxsrcMicrosoftDataSqlClientSqlConnection.cs:line 1853 at Microsoft.Data.SqlClient.SqlConnection.Open() in E:agent1\_work31ssrcMicrosoft.Data.SqlClientetfxsrcMicrosoftDataSqlClientSqlConnection.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 DevopsThe post mentionsI am running Windows 10 so I dont see why it would be trying to load a 32 bit version of sni.dllI can see in the Azure Artifiacts[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-nettrigger:- masterpool: 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[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 IssueWhen 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 解决方案 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) 这篇关于无法加载文件或程序集“Microsoft.Data.SqlClient"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-07 10:06