enable-migrations in x64 Project gets System.BadIm

2019-02-11 13:32发布

问题:

I have a project set to x64 (it's using some Nuget packages that are 64-bit only). Everything runs and deploys fine, but trying to run EF's enable-migrations at the Package Manager Console gets me a System.BadImageFormatException. The full exception:

PM> enable-migrations
System.BadImageFormatException: Could not load file or assembly  or one of its dependencies. An attempt was made to load a program with an incorrect format.
File name: 
   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.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.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean forIntrospection)
   at System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
   at System.Reflection.Assembly.Load(String assemblyString)
   at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.LoadAssembly(String name)
   at System.Data.Entity.Migrations.Design.ToolingFacade.GetContextTypeRunner.Run()
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
   at System.Data.Entity.Migrations.Design.ToolingFacade.GetContextType(String contextTypeName)
   at System.Data.Entity.Migrations.EnableMigrationsCommand.FindContextToEnable(String contextTypeName)
   at System.Data.Entity.Migrations.EnableMigrationsCommand.<>c__DisplayClass2.<.ctor>b__0()
   at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)

WRN: Assembly binding logging is turned OFF.
To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.
Note: There is some performance penalty associated with assembly bind failure logging.
To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog].

Could not load file or assembly  or one of its dependencies. An attempt was made to load a program with an incorrect format.

Note: I've removed the project name from the error message, both to make this easier to google and because it's irrelevant to this problem.

回答1:

The problem is that the enable-migrations command appears to have a hard-coded path where EF looks for built DLLs of your project at /bin/Debug, no matter what the actual build path is. When you change a Project to x64, Visual Studio quietly changes your project's build path to /bin/x64/Debug - while EF keeps looking in /bin/Debug. That causes this vague System.BadImageFormatException.

It's harmless to just change your Project build path to /bin/Debug and magically, everything begins working like it's supposed to.

Bug exists up to and including EF 6.1.0. Bug report posted.

Update: Microsoft has decided not to bother fixing the bug, closed as wontfix, because a workaround exists. Pretty bad behavior.



回答2:

As stated by Microsoft support: "the workaround is to swap to AnyCPU or x86 [before you] generate/run migrations and then swap back".

They also suggest: "[refactoring] the model/migrations into a separate project that is AnyCPU"



回答3:

The core issue was around the x64. In my scenario, I was trying to use the Azure Mobile Services Todo reference solution. In this solution, there is a Services solution, and 2 front end client ( Windows 8 and Windows Phone ) solutions.

In experimenting with the solution, I added offline support. Offline support implements SQLite, and SQLite requires configuring the Solution to use x64 or ARM for the respective native clients.

So changing the CPU target to solve for the SQLite support, I must have modified CPU x64 on the Services, and saved. When I saw my error of using x64 for the service, I changed back to Any CPU.

This all leads up to... when I next tried to add migrations, my .csproj file for the services was "corrupted" based on the information in this post. In my case I made the following change / update in the .csproj file of the service:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>

In my case,

<PlatformTarget/> 

was still set as x64.



回答4:

Go to IIS Manager > View Application Pool > Default Application Tool > Advance Settings... > Set 32 bits to true



回答5:

Don't be confused like me:

  1. Change Active Platform to AnyCPU from the ConfigurationManager (if it's missing - add it)
  2. Go to the properties of the project that contains the DbContext
  3. In the Build tab, change Platform target to AnyCPU
  4. Run the following command in Package Manager Console: Enable-Migrations -ProjectName ProjectNameThatContainsTheDContext