Rohan Bhatia
Rohan Bhatia

Reputation: 2020

Problem with EF Core migration on Azure Function v2 on .NET Core

I have a project called MyApp which contains Entity Framework Core Models. To create the initial database from those models I used the following command in the Package Manager Console of Visual Studio:

dotnet ef migrations -v add InitialCreate

The directory structure of my Project is something like this:

MyApp
|-bin
|   |-Debug
|   |   |-netcoreapp2.1
|   |   |  |-bin
.   .   .  |  |-...
.   .   .  |  |-MyApp.dll
.   .   .  |  |-...
           |-MyApp.deps.json
           |-MyApp.runtimeconfig.dev.json
           |-MyApp.runtimeconfig.json

The Problem

As I run the above command to create the initial database, the following error pops up:

An assembly specified in the application dependencies manifest
(MyApp.deps.json) was not found:
    package: 'MyApp', version: '1.0.0'
    path: 'MyApp.dll'

So, the command could not locate the MyApp.dll file which was in the bin directory.

This is clear from the following verbose output:

PM> dotnet ef migrations -v add InitialCreate
Using project 'C:\Users\rohan\Projects\MySolution\myproject\MyApp.csproj'.
Using startup project 'C:\Users\rohan\Projects\MySolution\myproject\MyApp.csproj'.
Writing 'C:\Users\rohan\Projects\MySolution\myproject\obj\MyApp.csproj.EntityFrameworkCore.targets'...
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=C:\Users\rohan\AppData\Local\Temp\tmp4BF.tmp /verbosity:quiet /nologo C:\Users\rohan\Projects\MySolution\myproject\MyApp.csproj
Writing 'C:\Users\rohan\Projects\MySolution\myproject\obj\MyApp.csproj.EntityFrameworkCore.targets'...
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=C:\Users\rohan\AppData\Local\Temp\tmpEB2.tmp /verbosity:quiet /nologo C:\Users\rohan\Projects\MySolution\myproject\MyApp.csproj
dotnet build C:\Users\rohan\Projects\MySolution\myproject\MyApp.csproj /verbosity:quiet /nologo

Build succeeded.

    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:17.49
dotnet exec --depsfile C:\Users\rohan\Projects\MySolution\myproject\bin\Debug\netcoreapp2.1\MyApp.deps.json 
--additionalprobingpath C:\Users\rohan\.nuget\packages --additionalprobingpath "C:\Program Files\dotnet\sdk\NuGetFallbackFolder" 
--runtimeconfig C:\Users\rohan\Projects\MySolution\myproject\bin\Debug\netcoreapp2.1\MyApp.runtimeconfig.json 
"C:\Program Files\dotnet\sdk\2.1.700\DotnetTools\dotnet-ef\2.1.11\tools\netcoreapp2.1\any\tools\netcoreapp2.0\any\ef.dll" 
migrations add InitialCreate 
--assembly C:\Users\rohan\Projects\MySolution\myproject\bin\Debug\netcoreapp2.1\MyApp.dll 
--startup-assembly C:\Users\rohan\Projects\MySolution\myproject\bin\Debug\netcoreapp2.1\MyApp.dll 
--project-dir C:\Users\rohan\Projects\MySolution\myproject\ --language C# 
--working-dir C:\Users\rohan\Projects\MySolution\myproject --verbose --root-namespace MyApp
dotnet : Error:
At line:1 char:1
+ dotnet ef migrations -v add InitialCreate
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Error::String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

  An assembly specified in the application dependencies manifest (MyApp.deps.json) was not found:
    package: 'MyApp', version: '1.0.0'
    path: 'MyApp.dll'

Basically, the dll file path in --assembly and --startup-assembly options are incorrect. This is because the generated (by the above command) MyApp.deps.json contains the following:

{
  "runtimeTarget": {
    "name": ".NETCoreApp,Version=v2.1",
    "signature": "..."
  },
  "compilationOptions": {},
  "targets": {
    ".NETCoreApp,Version=v2.1": {
      "MyApp/1.0.0": {
        "dependencies": {
          ...
        },
        "runtime": {
          "MyApp.dll": {}
        }
      },
      ...
    }
    ...
  }
  ...
}

Here, inside the runtime JSON object in the MyApp/1.0.0 contains the relative path to the dll file as MyApp.dll whereas it should have been bin/MyApp.dll.

What should I do so that correct path is written in the runtime JSON object?

Upvotes: 4

Views: 2842

Answers (2)

Marc Stevenson
Marc Stevenson

Reputation: 1100

After much research myself, I found this work around from here:

https://dev.to/azure/using-entity-framework-with-azure-functions-50aa

But needed to adapt it for a n-tier setup whereby the models were in another project (along with other projects). I needed to copy all dlls starting with 'Crank' (feature code name) not just the dll of the start up project.

The end fix was to add the following the following to the startup csproj

 <Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="copy /Y &quot;$(TargetDir)bin\Crank*.dll&quot; &quot;$(TargetDir)Crank*.dll&quot;" /></Target>

This I understand will copy the project dlls so that the EF add-migration and update-database can use them.

Note the step needed to set the environment variable also before running add-migration or update-database:

$env:CrankDealershipDatabase="Server=.\ss2016,1433;Database=CrankDealership_Develop;Trusted_Connection=True;MultipleActiveResultSets=true"

These were the packages at the time:

Microsoft.Azure.Functions.Extensions 1.0.0

Microsoft.EntityFrameworkCore.SqlServer 2.2.6

Microsoft.NET.Sdk.Functions 1.0.29

Microsoft.EntityFrameworkCore 2.2.6

Microsoft.EntityFrameworkCore.Design 2.2.6

Microsoft.EntityFrameworkCore.Tools 2.2.6

Microsoft.VisualStudio.Web.CodeGeneration.Design 2.2.3

Upvotes: 0

David
David

Reputation: 88

I've had a very similar issue. After hours of searching and experimenting, I found this post: https://github.com/aspnet/EntityFrameworkCore/issues/14679

Separating the database stuff into a separate Class Library project and then adding the IDesignTimeDbContextFactory fixed it for me.

Good luck

Upvotes: 4

Related Questions