I am trying to adopt Jimmy Bogard's ContosoUniversityCore project
I would like to do code first migrations, but not sure how to properly set it up.
I added Migrator.EF6.Tools to my project.
When I run Enable-Migrations
I get this error:
Exception calling "SetData" with "2" argument(s): "Type 'Microsoft.VisualStudio.ProjectSystem.VS.Implementation.Package.Automation.OAProject' in assembly 'Microsoft.VisualStudio.ProjectSystem.VS.Implementation, Version=14.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' is not
marked as serializable."
At C:\Users\SomeUser\.nuget\packages\entityframework\6.1.3\tools\EntityFramework.psm1:718 char:5
+ $domain.SetData('project', $project)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : SerializationException
Exception calling "SetData" with "2" argument(s): "Type 'Microsoft.VisualStudio.ProjectSystem.VS.Implementation.Package.Automation.OAProject' in assembly 'Microsoft.VisualStudio.ProjectSystem.VS.Implementation, Version=14.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' is not
marked as serializable."
At C:\Users\SomeUser\.nuget\packages\entityframework\6.1.3\tools\EntityFramework.psm1:719 char:5
+ $domain.SetData('contextProject', $contextProject)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : SerializationException
Exception calling "SetData" with "2" argument(s): "Type 'Microsoft.VisualStudio.ProjectSystem.VS.Implementation.Package.Automation.OAProject' in assembly 'Microsoft.VisualStudio.ProjectSystem.VS.Implementation, Version=14.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' is not
marked as serializable."
At C:\Users\SomeUser\.nuget\packages\entityframework\6.1.3\tools\EntityFramework.psm1:720 char:5
+ $domain.SetData('startUpProject', $startUpProject)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : SerializationException
System.NullReferenceException: Object reference not set to an instance of an object.
at System.Data.Entity.Migrations.Extensions.ProjectExtensions.GetPropertyValue[T](Project project, String propertyName)
at System.Data.Entity.Migrations.MigrationsDomainCommand.GetFacade(String configurationTypeName, Boolean useContextWorkingDirectory)
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)
Object reference not set to an instance of an object.
The real issue here is that there are different EF "flavours". Just go to EF root documentation and see the differences:
- EF (root documentation folder): https://docs.microsoft.com/en-us/ef/
- EF 6 migrations commands: https://dzone.com/articles/ef-migrations-command
- EF Core migrations commands: https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/migrations
- Migration Commands has changed a lot in .Net Core I recommend to
visit also: https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/dotnet
Here is my recipe to use migrations with EF 6 and .NET Core:
1st.- You must add these lines to the .csproj:
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="1.0.1" />
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.1" />
</ItemGroup>
Note: Version has changed
2nd.- Create a Context in your project like this:
public class YourContext : DbContext
{
#region Constructors
public YourContext()
{
}
public YourContext(DbContextOptions options) : base(options)
{
}
#region DbSets // YOUR DB SETS GO HERE...
#endregion DbSets
#region OnConfiguring // THIS HELPED ME A LOT:
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
// In order to be able to create migrations and update database:
if (!options.IsConfigured)
{
options.UseSqlServer("YourLocalConnectionStringShouldBeHere");
}
base.OnConfiguring(options);
}
#endregion
#region Model Creating
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Your Model Crerating Stuff
}
#endregion Model Creating
}
3rd.- ADD A MIGRATION:
Go to the project folder and, from cmd, type:
dotnet ef migrations add [NameOFYourMigrationGoesHere] -c YourContext
NOTE: Don't forget to add created files to source control, that's not done auto-magically
4rd.- UPDATE YOUR DB's:
4.a.- In docker -> You can run the project (entirely with Docker) and the migration would be applied at the first Context usage.
note: (It will use the configured connection string for that environment)
4.b.- Your Local DB -> Edit the Connection String hardcoded in ConfigurationContext.OnConfigure and run (from cmd console):
dotnet ef database update --context ConfigurationContext
I hope it helps you.
Juan
your EF6 project has to provide an implementation of IDbContextFactory. The EF6 command-line tools will find and use that implementation so they can instantiate the context. Here's an example.
public class SchoolContextFactory : IDbContextFactory<SchoolContext>
{
public SchoolContext Create()
{
return new EF6.SchoolContext("Server=(localdb)\\mssqllocaldb; Database=EF6MVCCore;Trusted_Connection=True;MultipleActiveResultSets=true");
}
}
In the Core project's Startup.cs file, set up the EF6 context for dependency injection (DI) in ConfigureServices. EF context objects should be scoped for a per-request lifetime.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
services.AddScoped<SchoolContext>(_ => new SchoolContext(Configuration.GetConnectionString("DefaultConnection")));
}
In Package Manager Console (PMC) for both projects, run the command Install-Package Entityframework.
In the class library project, create data model classes and a context class, and an implementation of IDbContextFactory.
In PMC for the class library project, run the commands Enable-Migrations and Add-Migration Initial. If you have set the ASP.NET Core project as the startup project, add -StartupProjectName EF6 to these commands.
in Startup.cs, register the context for DI in appsettings.json, add the connection string.
For more info visit
https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6
The problem is EF 6 migrations are not accustomed to work with the new csproj format.
What helped me was this project.
Check it out the instructions on its main page.
In general you just have to add the package to your project in the instructed way and migrations should then work.