Xamarin.Forms и EntityFrameworkCore 3.x, как правильно создать базу данных и применить миграции? - PullRequest
1 голос
/ 18 июня 2020

как правильно создать базу данных EF Core на устройстве Android / iOS с помощью Xamarin.Forms и EntityFrameworkCore?

Я столкнулся с проблемой EnsureCreated vs Migrate, и, поскольку я планирую изменить структуру базы данных в будущем, я хотел бы иметь возможность применить эти миграции к существующей базе данных , поэтому я выбрал подход Migrate.

Однако, когда я вызываю метод Migrate, кажется, что он не создает базу данных. Мне удалось заставить его работать, если я заранее скопирую предварительно сгенерированный файл базы данных на устройства, но это не то, что я хочу. Есть ли способ указать EF Core проверить, существует ли база данных, создать новую базу данных, если нет, а затем применить к ней ожидающие миграции?

Вот что я сделал на данный момент:

  1. Я создал стандартную библиотеку классов. net «Data», которая будет содержать все мои классы базы данных (контекст, модели и миграции).
  2. Я изменил TargetFramework проекта «Data» с <TargetFramework>netstandard2.0</TargetFramework> на <TargetFrameworks>netcoreapp2.0;netstandard2.0</TargetFrameworks>, чтобы я мог запускать на нем команды PM C.
  3. Я установил эти nuget пакеты в проект «Данные»:
    • EntityFrameworkCore
    • EntityFrameworkCore.Sqlite
    • EntityFrameworkCore.Tools
    • EntityFrameworkCore.Design
  4. Я создал класс контекста базы данных. Я сделал для него два конструктора. Значение по умолчанию будет использоваться только командами PM C для генерации миграций. Другой будет использоваться в производстве.
    public class MyTestContext : DbContext
    {
        private string _databasePath;

        public DbSet<Issue> Issues { get; set; }

        [Obsolete("Don't use this for production. This is only for creating migrations.")]
        public MyTestContext() : this("nothing.db")
        {

        }

        public MyTestContext(string databasePath)
        {
            _databasePath = databasePath;
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            //I've also tried Filename={_databasePath} here, didn't work either
            optionsBuilder.UseSqlite($"Data Source={_databasePath}");
        }
    }
Я создал класс тестовой модели, просто чтобы было с чем поиграть
    public class Issue
    {
        public string Id { get; set; }
    }
Я создал начальную миграцию, используя эту команду, которая успешно завершилась:
Add-Migration Migration001 -Context MyTestContext -Output Migrations
Я добавил вызов метода Migrate в App.xaml.cs моего проекта Xamarin.Forms, чтобы проверить, работает ли он.
    public partial class App : Application{

        //... other code

        protected override async void OnStart()
        {
            base.OnStart();

            using (var db = new MyTestContext(_dbPath))
            {
                try
                {
                    db.Database.Migrate();

                    db.Issues.Add(new Issue
                    {
                        Id = "TestIssueId"
                    });

                    db.SaveChanges();
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex);
                }
            }
        }

        //... other code

    }

Переменная _dbPath содержит это (на Android, где я его тестирую):

Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "test.db");

После всего этого я получаю следующее исключение:

Microsoft.Data.Sqlite.SqliteException: SQLite Error 1: 'no such table: Issues'.
...