0

Is it possible to access the same nuget package but different versions of it in the same netcore project?

I have a net core api that logs to elasticsearch. It uses the package: Serilog.Sinks.Elasticsearch - 6.5.0, which has Elasticsearch.Net - 6.0.0 as its own reference.

Everything works fine and has done so for months. But now when I for another functionality added Elasticsearch.Net - 7.0.0-alpha2 manually to the project the subnuget for Serilog.Sinks.Elasticsearch is also upgraded, which breaks the functionality.

The new code based on Elasticsearch.Net - 7.0.0-alpha2 works fine though.

Is there any way to force the nuget reference for Serilog.Sinks.Elasticsearch so it uses Elasticsearch.Net - 6.0.0 while my own new code uses Elasticsearch.Net - 7.0.0-alpha2?

Nugets before new code:

enter image description here

Nugets with new code:

enter image description here

Anthon Nilsson
  • 113
  • 1
  • 7
  • Breaks how? What error do you get? A compile-time error, a runtime error? Does it mention binding redirection perhaps? You can redirect calls to an older assembly version to the installed new version. In fact, adding a newer NuGet package version typically adds the required binding redirects in csproj – Panagiotis Kanavos May 21 '19 at 14:30
  • The latest version of Serilog.Sinks.Elasticsearch is 7.1 by the way. Both that and 6.5.0 depend on any Elasticsearch.Net version at or above 6.0. They don't have a hard dependency – Panagiotis Kanavos May 21 '19 at 14:33
  • The compiling and running of the application is still fine after the update of the nuget. But the logs are never sent to elasticsearch, instead they are written to the failuresink. The only difference to the progrem between correctly writing to elasticsearch or not is the version of Elasticsearch.Net. – Anthon Nilsson May 21 '19 at 18:53
  • That has nothing to do with assembly versioning. You're using an alpha version, it's bound to have issues. Why don't you use a stable version? The latest stable is 6.7.0 [released just 13 days ago](https://www.nuget.org/packages/Elasticsearch.Net/) – Panagiotis Kanavos May 22 '19 at 11:14
  • If you check [the release notes for 7.0 alpha 2](https://github.com/elastic/elasticsearch-net/releases/tag/7.0.0-alpha2) you'll see there some pretty big breaking changes : `Majority of response interfaces are gone`. That breaks *all* packages that haven't upgraded in the last .... two weeks. I suspect that's all of them – Panagiotis Kanavos May 22 '19 at 11:16
  • I had to use the 7.* version in order to do a _search in elasticsearch 7.0.1 database. I understand alpha is not stable, but it was the only one I got working with the new elasticsearch db. I'm actually using NEST 7.0.0-alpha2. If it had not been for serilog malfunction problem would have been solved. Anyhow, I solved my initial issue with not using NEST or Elasticsearch.Net at all. Instead I'm only doing REST requests with net core HttpClient instead and parsing the results myself. – Anthon Nilsson May 22 '19 at 14:30

2 Answers2

1

Mostly no, but a little bit yes. It depends :)

The build system (NuGet, the .NET SDK, msbuild) creates build output with all the dlls in one directory. If you need elasticsearch.dll from two different versions of the package, how could this work? Obviously you can't have two files with a single name, so at least one would need to be renamed, but then when the CLR needs to load elasticsearch.dll, how would it know that it has a different name, and how would it know what the new name is?

So, using the built-in functionality in the build system it's not possible.

However, the .NET Framework does support loading different versions of a dll, you just need to do work in copying files and to tell it where the different versions are. Using the codebase element in an app.config file, you can tell it where the dlls are. You can see an example of this in use in %userprofile%\AppData\Local\Microsoft\VisualStudio\{your vs version folder}\devenv.exe.config. The vast majority of this file is binding redirects and codeBase elements. You'll need more advanced build scripts that just running dotnet publish to get all your dlls in the desired locations. It will probably prevent you from being able to start a debug session from VS, but you can always attach VS as a debugger to a running process, so it's still possible to debug, it's just harder.

This might be .NET Framework only. If it doesn't work on .NET Core, you can look into AssemblyLoadContext, but I've never seen a complete example, other than a no-op implementation that just uses the default context, but I think that might prevent loading multiple versions at the same time.

Another example of loading multiple versions of an assembly in the same process on the .NET Framework is using App Domains. But that's definitely .NET Framework only, in case you need to support .NET Core or the future One.NET (.NET 5). AssemblyLoadContext is the closest thing to app domains in .NET Core, but isn't the same thing.

To the best of my knowledge, Mono doesn't support loading multiple versions of an assembly at the same time, but my guess is that this will change once .NET 5 is released. But it's a guess that lacks any evidence or inside knowledge whatsoever.

zivkan
  • 12,793
  • 2
  • 34
  • 51
  • On the contrary, it's possible and quite common to have different DLLs that require different versions of another assembly. The solution is to use binding redirects – Panagiotis Kanavos May 21 '19 at 14:31
  • unless the two versions of the dll are not binary compatible and result in runtime errors, which is what I assume the problem from the question is about. – zivkan May 21 '19 at 15:03
  • additionally, the .NET Core SDK automatically adds binding redirects to the app.config put in the bin folder on build. From the screenshots in the question, the asker is obviously using SDK style projects. Therefore, binding redirects should also be used, but if problems exist it didn't help. But you're right, they are generally the solution. – zivkan May 21 '19 at 15:09
0

The problem that you are having is known as "Dll Hell", there are many approach to manage it, for example:

  • Try to use strong name libraries and install them into the Global Assembly Cache
  • Apply an abstraction layer between dependencies
  • Encapsulate the use into different context

Maybe this old post can also help you.

ganchito55
  • 3,559
  • 4
  • 25
  • 46
  • That's not what DLL Hell refers to. This has nothing to do with the GAC, it's about NuGet packages. The GAC, or any central location actually makes such issues *worse* – Panagiotis Kanavos May 21 '19 at 14:27