1
votes

I am having a very difficult time tracking down the cause of a bad assembly reference issue in my C#/Azure application. What I'm looking for is not so much for someone to tell me the exact solution to my problem but how to find how what assembly the system is attempting to load and how to find out why it's doing this.

The problem came about when we upgraded Azure tools. What's really weird is that the error only occurs (from what I can tell) when I attempt to call a database function via Entity Framework. EF does all of this implicit assembly loading and some how it is getting confused and trying to load Microsoft.ServiceBus 1.8.0.0 (or is finding that assembly) instead of version 2.2.0.0.

We are using Entity Framework 4.0. And FYI, we can call stored procedures and do other kinds of queries just fine. It's only db function calls that cause this particular issue.

I have searched high and low through my application and can find no references to 1.8.0.0 and no stray 1.8.0.0 dlls anywhere. It's possible that we have an out dated reference to some 3rd party library that is holding on to a reference to 1.8.0.0 but I think this is unlikely.

Still, my goal here is not for someone to tell me that X is my problem, but to give me a clue as to how I can spy on Entity Framework and find out why it's trying to load that assembly and what it expects to find and what it is actually finding.

Here is my full stacktrace.

Could not load file or assembly 'Microsoft.ServiceBus, Version=1.8.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040) at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) at System.Reflection.Assembly.Load(AssemblyName assemblyRef) at System.Data.Metadata.Edm.MetadataAssemblyHelper.SafeLoadReferencedAssembly(AssemblyName assemblyName) at System.Data.Metadata.Edm.MetadataAssemblyHelper.d__0.MoveNext() at System.Data.Metadata.Edm.AssemblyCache.LoadAssembly(Assembly assembly, Boolean loadReferencedAssemblies, ObjectItemLoadingSessionData loadingData) at System.Data.Metadata.Edm.AssemblyCache.LoadAssembly(Assembly assembly, Boolean loadReferencedAssemblies, ObjectItemLoadingSessionData loadingData) at System.Data.Metadata.Edm.AssemblyCache.LoadAssembly(Assembly assembly, Boolean loadReferencedAssemblies, ObjectItemLoadingSessionData loadingData) at System.Data.Metadata.Edm.AssemblyCache.LoadAssembly(Assembly assembly, Boolean loadReferencedAssemblies, ObjectItemLoadingSessionData loadingData) at System.Data.Metadata.Edm.AssemblyCache.LoadAssembly(Assembly assembly, Boolean loadReferencedAssemblies, KnownAssembliesSet knownAssemblies, EdmItemCollection edmItemCollection, Action`1 logLoadMessage, Object& loaderCookie, Dictionary`2& typesInLoading, List`1& errors) at System.Data.Metadata.Edm.ObjectItemCollection.LoadAssemblyFromCache(ObjectItemCollection objectItemCollection, Assembly assembly, Boolean loadReferencedAssemblies, EdmItemCollection edmItemCollection, Action`1 logLoadMessage) at System.Data.Metadata.Edm.ObjectItemCollection.ImplicitLoadAllReferencedAssemblies(Assembly assembly, EdmItemCollection edmItemCollection) at System.Data.Metadata.Edm.MetadataWorkspace.ImplicitLoadAssemblyForType(Type type, Assembly callingAssembly) at System.Data.Objects.ObjectContext.CreateQuery[T](String queryString, ObjectParameter[] parameters) at Pallas.FlightBridge.Services.Internal.Data.Model.FlightBridgeDatabaseContext.TripPermissions(Nullable`1 companyPersonId) in c:\Users\RMacgrogan\dev\flightbridge\BaseOps\trunk\FB Version 7.8\code\InternalServices\Data\Model\FlightBridgeDataModel.Designer.cs:line 3778 at Pallas.FlightBridge.Services.Internal.Data.Repository.TripRepository.GetTripAndOrdersAndTravelers(Int32 tripId, Int32 companyPersonId) in c:\Users\RMacgrogan\dev\flightbridge\BaseOps\trunk\FB Version 7.8\code\InternalServices\Data\Repository\TripRepository.cs:line 50
1
Sounds like you need a binding redirect.danludwig
Could not load file or assembly 'Microsoft.ServiceBus, Version=1.8.0.0'. Check your references for this one.Tico
Tico we don't have any references at all to Service Bus 1.8.0.0 anywhere in our code base that I can find. I have searched everywhere. If you have a suggestion about how I can verify that we really are not referencing 1.8 I would be happy to hear it.Robert MacGrogan

1 Answers

3
votes

We had a similar issue after an azure tools upgrade. With ours, it was looking for a differnet version of Microsoft.WindowsAzure.Storage. This fixed it for us. This is from an app.config in a worker role, but the same section is also valid in a web.config:

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity name="Microsoft.WindowsAzure.Storage" publicKeyToken="31bf3856ad364e35" />
      <bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
    </dependentAssembly>
  </assemblyBinding>
</runtime>

So for you, it seems a similar binding redirect would be needed in the problematic role's configuration file. Something like this:

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity name="Microsoft.ServiceBus" publicKeyToken="31bf3856ad364e35" />
      <bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
    </dependentAssembly>
  </assemblyBinding>
</runtime>

Why does this happen?

When Microsoft builds these libraries like EF, WindowsAzure Storage, etc, they take dependencies on other libraries. At the time the dll was built, they might have taken a dependency on say version 1.8 of a library like Microsoft.ServiceBus. Often, those dependencies are part of the .NET framework, or something like the Azure SDK.

Later, they come out with newer versions of these libraries. Your project might take a dependency on a newer version of the .NET framework, Azure SDK, or a specific library, with a different version than the original library's dependency -- say 2.2 instead of 1.8. The library in question (EF) looks for the version it was compiled against (1.8), and throws up an exception even if you have a newer version of the dll (2.2) that would work perfectly fine with it. The solution is to configure your app with a binding redirect to tell the dependency "hey, it's ok to use a newer version of this".

In fact, if you have a multi-project solution, nuget has started putting these binding redirects in other projects whenever you install new package. It basically tells all of the projects in the solution, "hey if you are using this library, there is a new version of it in the solution now. Use this new version instead of any previous versions you were using before."