Entity Framework Core migrations are really powerful and most C# developers make good use of them. They’re very easy to use, you can work with them either on Powershell or on the Package Manager Console. Most of the time whenever you make some change in your Entities you can open up a terminal and hit “dotnet ef migrations add” followed by a name for your new migration.
This will work on all ASP.NET Core projects by default. However, when creating a Service Fabric Stateless or Stateful microservice, things are different. If you attempt to run this command it won’t work. You will receive an error like the following:
Unable to create an object of type ‘AppDbContext’. Add an implementation of ‘IDesignTimeDbContextFactory
‘ to the project, or see https://go.microsoft.com/fwlink/?linkid=851728 for additional patterns supported at design time.
The first step to debugging this error is to re-run the command in verbose mode:
dotnet ef migrations add "InitialMigration" --verbose
By taking a closer look to the console output we can see that the actual error that broke the operation is the following exception:
System.MissingMethodException: No parameterless constructor defined for this object.
Every time you run that command without supplying any other arguments, .NET Core will re-build your project, execute Program.cs to load the webhost and more specifically the Startup file. This is important because without the startup file, it will be impossible for the runtime to know how to instantiate the Database Context.
This is an example of an AppDbContext:
We only have one entity, the ToDo model and we inherit from Entity Framework’s DbContext. If you look at the constructor, you can see that in order to create a new instance of this class we have to pass an argument of type DbContextOptions. The most common option in that object is the connection string that will allow Entity Framework to locate our database. The options object is created by a DbContextOptionsBuilder in the startup class at the time of registration like this:
So what is really happening is that the runtime can’t provide DbContextOptions so it resorts to calling the parameter-less constructor. But there’s no such thing. We haven’t implemented one. And it’s neither the best choice nor possible sometimes. So, the framework suggests we implement the IDesignTimeDbContextFactory interface. It’s not necessary, we can quickly solve this issue by adding the following lines to our Program.cs file:
This function will build a webhost and load the Startup file. That way, when .NET Core builds the project it will know how to create an instance of the DBContext because it will be registered with the ASP.NET Core Dependency Injection Container
Note that attempting to call this method from inside Main will cause your Service Fabric build to fail because it will hijack the default port 5000. Doing so will cause any subsequent microservice build to fail.