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.
You can't put an EF6 context in an ASP.NET Core project because . NET Core projects don't support all of the functionality that EF6 commands such as Enable-Migrations require.
Adding a Migration So, firstly, you need to create a migration. Open the Package Manager Console from the menu Tools -> NuGet Package Manager -> Package Manager Console in Visual Studio and execute the following command to add a migration.
Create a new migration and generate a SQL script for it. In your database, delete all rows from the migrations history table. Insert a single row into the migrations history, to record that the first migration has already been applied, since your tables are already there.
The real issue here is that there are different EF "flavours". Just go to EF root documentation and see the differences:
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://learn.microsoft.com/en-us/aspnet/core/data/entity-framework-6
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With