Entity Framework c предустановленной БД в вашем приложении на .NET MAUI

от автора

Данный текст является логичным продолжением статьи Entity Framework c Code-First миграциями для .NET MAUI. В ней рассказывалось как подключить и использовать, возможно, уже привычную вам по работе с апи технологию работы с БД Entity Framework теперь в вашем мобильном приложении.

Данная статья явно требует продолжения для практического использования: когда у вас уже есть некая предварительно заполненная база данных, и ее надо выпустить вместе с приложением.

Итак, допустим, в процессе разработки мы заполнили БД нужными вам значениями и теперь вы хотите чтобы они были доступны всем пользователям. Покажем на примере.

Кладем ваш файл базы данных в Resources/Raw/Db/app.db3 — Build Action: MauiAsset. Замечательно, файл уже с нами.

Теперь, чтобы его реально использовать при исполнении приложения, надо переложить файл из ресурсов в папку уже развернутого после установки приложения.

Регистрируем наш контекст таким образом (MauiProgram.cs):

private static object _lockDb = new(); //не нужны лишние проблемы  public static MauiApp CreateMauiApp(){  ... services.AddTransient<LocalDatabase>((services) => {     lock (_lockDb)     {         var filenameDb = Path.Combine(FileSystem.AppDataDirectory, "app.db3");         if (!File.Exists(filenameDb))         {             using var stream = FileSystem.OpenAppPackageFileAsync("ML/app.db3").GetAwaiter().GetResult();             using (var memoryStream = new MemoryStream())             {                 stream.CopyTo(memoryStream);                 File.WriteAllBytes(filenameDb, memoryStream.ToArray());             }         }         return new LocalDatabase(filenameDb);     } }); ...  }

Отлично, теперь наша пре-заполненная база всегда с нами на продакшене. Мы проверили, развернут ли файл бд в папке, и закрыли проблему. Одновременно используем лок, чтобы не получить одновременную попытку инициализации бд из разных потоков.

Напоследок, напомним, кто-такая была LocalDatabase:

public class LocalDatabase : DbContext {  #region CONSTRUCTOR   //parameterless constructor must be above the others,  //as it seems that EF Tools migrator just takes the .First() of them   /// <summary>  /// Constructor for creating migrations  /// </summary>  public LocalDatabase()  {      File = Path.Combine("../", "UsedByMigratorOnly1.db3");      Initialize();  }   /// <summary>  /// Constructor for mobile app  /// </summary>  /// <param name="filenameWithPath"></param>  public LocalDatabase(string filenameWithPath)  {      File = filenameWithPath;      Initialize();  }  void Initialize()  {      if (!Initialized)      {          Initialized = true;           SQLitePCL.Batteries_V2.Init();           //Database.EnsureDeleted(); //use in dev process when needed           Database.Migrate();      }  }  public static async Task<LocalDatabase> CreateAsync(string filenameWithPath)  {      var instance = new LocalDatabase(filenameWithPath);      await instance.InitializeAsync();      return instance;  }  private async Task InitializeAsync()  {      if (!Initialized)      {          Initialized = true;           SQLitePCL.Batteries_V2.Init();           await Database.MigrateAsync();      }  }   public static string File { get; protected set; }  public static bool Initialized { get; protected set; }   protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)  {      optionsBuilder          .UseSqlite($"Filename={File}");  }   #endregion   public void Reload()  {      Database.CloseConnection();      Database.OpenConnection();  } }

Не забудьте ознакомиться с предыдущей статьей: Entity Framework c Code-First миграциями для .NET MAUI

Надеюсь, этот материал был вам полезен, увидимся на берегах МАУИ!


ссылка на оригинал статьи https://habr.com/ru/articles/841272/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *