Я надеюсь, вы прочитали "превью", поэтому, без лишних слов приступаем сразу к делу!

Создаем два проекта, в одном будет наш Maui, а в другом контекст.

Вот такая вот структура( надеюсь к названиям не прикапываются)
Вот такая вот структура( надеюсь к названиям не прикапываются)

Создадим простенькие модели в MauiMigrationsExample.Dal

namespace MauiMigrationsExample.Dal.Models;

public class Author
{
    public int Id { get; set; }
    public string Name { get; set; } = null!;

    public List<Book> Books { get; set; } = null!;
}

public class Book
{
    public int Id { get; set; }
    public string Name { get; set; } = null!;

    public int AuthorId { get; set; }
    public Author Author { get; set; } = null!;
}

А теперь самое важное! Я не хочу что бы настройка контекста происходила в Dal. Поэтому пойдем на "просто" решение: пропишем следующее условие в MauiMigrationsExample.Dal.csproj

<PropertyGroup Condition="'$(Configuration)'=='Migrate'">
  <DefineConstants>EF_MIGRATION</DefineConstants>
</PropertyGroup>

Ага, мы просто добавили константу для препроцессор если конфигурация равна Migrate. Дело в том что сам хочет dotnet-ef что бы контекст передавался в ServiceCollection. Это можно исправить с параметром --context(или -c) , но тогда обязательно нужно реализовать OnConfiguring. Однако как я сказал выше " Я не хочу что бы настройка контекста происходила в Dal".

Поэтому, далее пишем уже сам контекст, используя директивы препроцессора.

using MauiMigrationsExample.Dal.Models;
using Microsoft.EntityFrameworkCore;
using SQLitePCL;

namespace MauiMigrationsExample.Dal;
public class MauiDbContex : DbContext
{
    public DbSet<Author> Authors { get; set; } = null!;
    public DbSet<Book> Books { get; set; } = null!;

#if !EF_MIGRATION
    public MauiDbContex(DbContextOptions options) : base(options)
    {
        Batteries_V2.Init();
    }

#else
    public MauiDbContex()
    {
        Batteries_V2.Init();
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlite($"Filename=sad");
    }
#endif

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
      ...
    }
}

И пишем следующую команду в корневой папке MauiMigrationsExample.Dal c параметром --configuration

 dotnet ef migrations add InitialCreate -c MauiDbContex --configuration Migrate

Если все сработало, то отлично! В следующий раз нам не нужно явно указывать контекст, но придется все так же писать --configuration Migrate

Ну теперь перейдем к настройке MauiMigrationsExample. Добавляем контекст :

builder.Services.AddDbContext<MauiDbContex>(options =>
        {
            var dbPath = Path.Combine(FileSystem.AppDataDirectory, "maui.sqlite");
            options.UseSqlite($"Filename={dbPath}");
        });

И настраиваем ваш App

using MauiMigrationsExample.Dal;
using Microsoft.EntityFrameworkCore;

namespace MauiMigrationsExample;

public partial class App : Application
{
	public App(MauiDbContex context)
	{
        MigrateIfHasMigration(context);

		InitializeComponent();

		MainPage = new AppShell();
	}

    private static void MigrateIfHasMigration(MauiDbContex contex)
    {
        if (contex.Database.GetPendingMigrations().Any())
        {
            contex.Database.Migrate();
        }
    }
}

Круть, все должно работать теперь. Спасибо за ваше внимание.

Комментарии (1)


  1. mayorovp
    00.00.0000 00:00
    +6

    Условная компиляция тут лишняя, как и отдельная конфигурация проекта.


    На самом деле всё что вам нужно — это создать вспомогательный класс, реализующий IDesignTimeDbContextFactory<ВашКонтекст>. Увидев такой класс, dotnet ef автоматически начнёт его использовать. Ну а вы внутри можете создать контекст для нужд миграций как угодно.