Данный текст является логичным продолжением статьи 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/
Добавить комментарий