Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to setup EF6 Migrations with ASP.NET Core

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.
like image 758
Pet Mor Avatar asked Feb 12 '17 02:02

Pet Mor


People also ask

Can I use EF6 with ASP NET core?

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.

How do I create a migration file in .NET core?

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.

How do I run down EF core 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.


2 Answers

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://learn.microsoft.com/en-us/ef/
  • EF 6 migrations commands: https://dzone.com/articles/ef-migrations-command
  • EF Core migrations commands: https://learn.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://learn.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

like image 141
Juan Avatar answered Oct 13 '22 03:10

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

like image 1
lazydeveloper Avatar answered Oct 13 '22 02:10

lazydeveloper