Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Entity Framework Core migrations for class library project

This seem to be an issue that have been fixed already, at least for the SQLite databases.

My solution consists of 3 projects:

  1. WPF project (default startup project) (.NET Framework 4.7),
  2. "Core" project holding the view model and non-UI stuff - Class library project (.NET Standard 2.0)
  3. "Relational" project holding all of the Entity Framework data layer - I like to keep those separated (.NET Standard 2.0)

I have installed the following packages into the main WPF project:

Microsoft.EntityFrameworkCore.Tools
Microsoft.EntityFrameworkCore.Design

Projects 2 and 3 are referenced in my main WPF project. So basically, it should be enough for the EF to resolve the DbContextes.

However, it's not - as running Add-Migration on my WPF project results in:

PM> Add-Migration "Initial"
No DbContext was found in assembly 'TestWPFProject'. Ensure that you're using the correct assembly and that the type is neither abstract nor generic.

Switching to project 3 as default in the Package Manager Console results in:

PM> Add-Migration "Initial"
Unable to create an object of type 'ClientDbContext'. Add an implementation of 'IDesignTimeDbContextFactory<ClientDataStoreDbContext>' to the project, or see https://go.microsoft.com/fwlink/?linkid=851728 for additional patterns supported at design time.

How can I properly use EF Core migrations with my class library project and WPF project?

like image 360
Lucas Avatar asked Jul 03 '18 02:07

Lucas


People also ask

How do I add EDMX file to class library project?

edmx . Go to solution Explorer > select Satyadatabasemodel.Context.tt under Satyadatabasemodel. edmx > Right click and Go to Properties > Enter "Custom Tool Namespace" value. Our class library project name is "Entities" > Save.

How do I run EF core migrations?

Install the tools First, you'll have to install the EF Core command-line tools: We generally recommend using the . NET Core CLI tools, which work on all platforms. If you're more comfortable working inside Visual Studio or have experience with EF6 migrations, you can also use the Package Manager Console tools.

Should I use EF6 or EF core?

Keep using EF6 if the data access code is stable and not likely to evolve or need new features. Port to EF Core if the data access code is evolving or if the app needs new features only available in EF Core. Porting to EF Core is also often done for performance.


1 Answers

I reproduced your solution and found... a solution :)

  1. "Core" project - called ClassLibrary1
  2. "Relational" project - called EFClssLibrary
  3. WPF App project - called WpfApp1

Let's get to deepen.


1. Core project

Name: ClassLibrary1.

Type: .NET Standard 2.0 class library.

Dependencies: none.

In my test solution, it contains only one class, a model called Person.

Person.cs

namespace ClassLibrary1
{
    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }
    }
}

2. Relational project

Name: EFClassLibrary.

Type: .NET Standard 2.0 class library.

Dependencies:

  • ClassLibrary1
  • Microsoft.EntityFrameworkCore (v2.1.1)
  • Microsoft.EntityFrameworkCore.SqlServer (v2.1.1)
  • Microsoft.EntityFrameworkCore.Tools (v2.1.1)

This project, in my test solution, contains only one class: the database context.

ClientDbContext.cs

using ClassLibrary1;
using Microsoft.EntityFrameworkCore;

namespace EFClassLibrary
{
    public class ClientDbContext : DbContext
    {
        const string connectionString = "Server=(localdb)\\mssqllocaldb;Database=ClientDb;Trusted_Connection=True;";

        public ClientDbContext() : base() { }

        public ClientDbContext(DbContextOptions<ClientDbContext> options) : base(options) { }

        public DbSet<Person> People { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(connectionString);
        }
    }
}

Connection string

In this class a defined an used the connection string to connect to the database (assuming it's LocalDb SQL Server). If you want to put the connection string in a config file, you could add a shared config file in your solution and then reference that file in your App.config file (for more informartion take a look at this page)

Configuring the target framework

In order to be able to add migrations on this project without setting as startup project other projects, you must set the target framework. Right click on the project and click on the Edit EFClassLibrary.csproj entry. Below the <TargetFramework>netstandard2.0</TargetFramework> line, you should add another line which specify which framework you want to target. To target the .NET Framework 4.7 you should add

<TargetFramework>net47</TargetFramework>

A list of all allowed values can be found here.

My EFClassLibrary.csproj look like the code below after adding the .NET Framework 4.7 as target.

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <TargetFramework>net47</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.1.1" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj" />
  </ItemGroup>

</Project>

Adding migrations

Now you are ready to add your first migration. Open the Package Manager Console and set as default project the EFClassLibrary. Also, set that project as startup project (right-click on the project and click on the Set as startup project entry).

Type

PM> Add-Migration Initial

then

PM> Update-Database

3. WPF App project

Name: WpfApp1.

Type: WPF Application using .NET Framework 4.7.

Dependencies:

  • ClassLibrary1
  • EFClassLibrary
  • Microsoft.EntityFrameworkCore (v2.1.1)

In this project I added no files. A just edited the MainWindow.xaml.cs file to check that everything works correctly.

MainWindow.xaml.cs

using ClassLibrary1;
using EFClassLibrary;
using System.Windows;

namespace WpfApp1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            var db = new ClientDbContext();

            db.People.Add(new Person()
            {
                Name = "Omar"
            });

            db.SaveChanges();
        }
    }
}

Hope it helps :)

like image 148
Omar Muscatello Avatar answered Sep 28 '22 04:09

Omar Muscatello