Для взаимодействия с SQLite в Xamarin Forms мы можем использовать Entity Framework Core, что значительно облегчает работу с базой данных. Рассмотрим, как работать с EF Core в Xamarin Forms. Для начала содадим стандартный проект Xamarin Forms по типу Blank. Допустим, он будет называться EFCoreApp
И первым делом добавим в главный проект решения через Nuget пакет Microsoft.EntityFrameworkCore.Sqlite:
При добавлении пакета следует учитывать версию .NET Standard, на которую он ориентирован. Так, последняя на данный момент версия пакета - Microsoft.EntityFrameworkCore.Sqlite 5.0 ориентирована на .NET Standard 2.1. Однако главный проект Xamarin Forms использует по умолчанию версию .NET Standard 2.0. То есть в данном случае мы столкнемся с несовместимостью. В этом случае нам надо либо установить Microsoft.EntityFrameworkCore.Sqlite более ранних версий, например, 3.1, 3.0, 2.2.
Если же мы все-таки хотим использовать версию пакета Microsoft.EntityFrameworkCore.Sqlite 5.0 или выше, то можно изменить вверсию .NET Standard на 2.1 в свойствах главного проекта. При компиляции под Android/iOS в этом случае никакх проблем не возникнет. Правда, в этом случае мы не сможем использовать Microsoft.EntityFrameworkCore.Sqlite 5.0 в проекте для UWP, поскольку он также нацелен на .NET Standard 2.0.
После добавления пакета определим в главном проекте класс Friend - модель, с которой мы будем работать:
public class Friend { public int Id { get; set; } public string Name { get; set; } public string Email { get; set; } public string Phone { get; set; } }
Также в главный проект добавим новый класс ApplicationContext:
using Microsoft.EntityFrameworkCore; namespace EFCoreApp { public class ApplicationContext : DbContext { private string _databasePath; public DbSet<Friend> Friends { get; set; } public ApplicationContext(string databasePath) { _databasePath = databasePath; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlite($"Filename={_databasePath}"); } } }
Данный класс представляет контекст данных, через который мы будем взаимодействовать с базой данных SQLite. Через конструктор объект этого класса получает в переменную _databasePath путь к базе данных. Стоит отметить, что в зависимости от целевой ОС путь к базе данных может отличаться.
Поскольку путь для разных ОС отличается, нам необходимо найти способ получения этого пути. И для этого воспользуемся механизмом внедрения зависимостей. В частности, определим в главном проекте интерфейс IPath:
public interface IPath { string GetDatabasePath(string filename); }
Через метод GetDatabasePath
мы будем получать из разных ОС путь к базе данных.
Теперь добавим в проекты для конкретных ОС реализацию этого интерфейса. В частности, в проект для Android добавим класс AndroidDbPath:
using System; using EFCoreApp.Droid; using System.IO; using Xamarin.Forms; [assembly: Dependency(typeof(AndroidDbPath))] namespace EFCoreApp.Droid { public class AndroidDbPath : IPath { public string GetDatabasePath(string filename) { return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), filename); } } }
В проект для iOS добавим класс IosDbPath:
using System; using Xamarin.Forms; using System.IO; using EFCoreApp.iOS; [assembly: Dependency(typeof(IosDbPath))] namespace EFCoreApp.iOS { public class IosDbPath : IPath { public string GetDatabasePath(string sqliteFilename) { // определяем путь к бд return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "..", "Library", sqliteFilename); } } }
И в проект для UWP добавим класс UwpDbPath:
using EFCoreApp.UWP; using Xamarin.Forms; using System.IO; using Windows.Storage; [assembly: Dependency(typeof(UwpDbPath))] namespace EFCoreApp.UWP { public class UwpDbPath : IPath { public string GetDatabasePath(string sqliteFilename) { return Path.Combine(ApplicationData.Current.LocalFolder.Path, sqliteFilename); } } }
Теперь создадим простейший CRUD-интерфейс для работы с БД через Entity Framework Core.