SQLite и Entity Framework

Добавление SQLite и Entity Framework в проект UWP

Последнее обновление: 15.04.2017

SQLite являются официально рекомендуемой системой управления баз данных для создания локального хранилища данных в Windows 10. SQLite обладает такими преимуществами, как компактность, кроссплатформенность, переносимость, ее не надо разворачивать на сервере, что делает ее очень удобным инструментом в мобильной разработке для разных ОС. Рассмотрим, как мы можем использовать SQLite при программирования в приложениях Universal Windows Platform. Прежде всего создадим новый проект, который назовем SQLiteApp.

Прежде всего для работы с SQLite нам надо устанавить для Visual Studio соответствующее расширение. Для этого в Visual Studio перейдем к пункту меню Tools -> Extensions and Updates. И здесь среди всех расширений нам надо установить расширение SQLite for Universal App Platform:

SQLite for Universal App Platform

Чтобы быстрее найти нужное расширение, надо в левом списке перейти к пункту Online и ввести в окно поиска SQLite.

Для работы с SQLite в приложении на UWP мы можем использовать разные подходы: либо работать с SQLite через одну из библиотек, которых довольно много в репозитории NuGet, либо использовать Entity Framework Core, который абстрагирует от структуры базы данных и позволяет работать с данными как с объектами стандартных классов языка C#. Наиболее простым и рекомендуемым подходом является использование Entity Framework, и в данной теме мы как раз и будем применять этот подход. Поэтому добавим пакеты Entity Framework в проект. Для работы нам понадобятся два пакета: Microsoft.EntityFrameworkCore.SQLite (непосредственно для взаимодействия с БД SQLite) и Microsoft.EntityFrameworkCore.Tools (для генерации базы данных).

При этом следует учитывать, что начиная с версии 2.0 Entity Framework поддерживает .NET Standard 2.0. UWP тоже поддерживает .NET Standard 2.0, но начиная с версии UWP 6.0, которая применяется в Windows 10 Fall Creators Update. То есть если наш проект в качестве минимальной версии использует версию Windows, которая вышла до Windows 10 Fall Creators Update, то мы можем в проекте использовать только EF Core 1.X. Если же проект в качестве минимальной и целевой версии применяет Windows 10 Fall Creators Update или более новую, то можно использовать EF Core 2.x.

Например, в моем случае (да и как правило, по умолчанию) в качестве минимальной версии применяется Windows 10 November Update:

.NET Standard 2.0 в UWP

Минимальная версия среды указывается при создании проекта и потом ее можно увидеть и изменить в свойствах проекта.

Поскольку минимальная версия Windows 10 November Update использует версию UWP, которая не применяет .NET Standard 2.0, то для работы мне надо установить версии пакетов Entity Framework Core 1.x.

EntityFramework Core и SQLite в UWP

Соответственно если бы проект использовал в качестве целевой и минимальной версий Windows 10 Fall Creators Update или более новую:

.NET Standard 2.0 в Universal Windows Platform

То мы могли бы использовать пакеты Entity Framework Core версий 2.х:

EntityFramework и SQLite в UWP

Теперь создадим модели, которые будут описывать данные и объекты которых будут храниться в бд SQLite. Для этого добавим в проект два класса. Класс Phone, который будет представлять модель телефона:

public class Phone
{
    public int Id { get; set; }
    public string Title { get; set; }
    public int Price { get; set; }
	
	public int CompanyId { get; set; }
    public Company Company { get; set; }
}

И класс Company, который представляет компанию-производителя телефона:

using System.Collections.Generic;

public class Company
{
    public int Id { get; set; }
    public string Name { get; set; }
	
	public List<Phone> Phones { get; set; }
	
	public override string ToString()
    {
        return Name;
    }
}

Итак, у нас здесь две модели, которые связаны связью "один-ко-многим", то есть одной компании может принадлежать много телефонов. А модель телефона хранит ссылку на определенную компанию.

При использовании Entity Framework нам надо учитывать некоторые условности. Во-первых, каждая модель должна иметь свойство-уникальный идентификатор, который должен называться Id или по шаблону [Класс]Id, например, для класса Phone это было бы свойство PhoneId. По этому уникальному идентификатору данные будут уникально различаться в базе данных.

Во-вторых, для создания связи "один-ко-многим" зависимая модель должна содержать ключ. В нашем случае зависимой моделью является Phone, поэтому он определяет ключ в виде двух свойств:

public int CompanyId { get; set; }
public Company Company { get; set; }

Свойство CompanyId хранит идентификатор модели Company, которая связана с данной моделью Phone. А свойство Company является ссылкой на этот связанный объект Company.

Для хранения всех объектов Phone в классе Company определено свойство

public List<Phone> Phones { get; set; }

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

Итак, добавим в проект новый класс MobileContext:

using Microsoft.EntityFrameworkCore;

public class MobileContext : DbContext
{
    public DbSet<Company> Companies { get; set; }
    public DbSet<Phone> Phones { get; set; }
	
	public MobileContext()
	{
		Database.EnsureCreated();
	}
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlite("Filename=Mobile.db");
    }
}

Класс контекста данных должен быть унаследован от базового класса DbContext, а для взаимодействия с таблицами в базе данных в нем определяются свойства по типу DbSet<T>. То есть через свойство Companies будет идти взаимодействие с таблицей компаний, а через свойство Phones - взаимодействие с таблицей телефонов.

Теперь нам нужна сама база данных. Здесь есть два варианта:

  • У нас нет начальных данных и соответственно базы данных, однако при работе приложения после установки приложения на устройство она может потребоваться. Поэтому имеет смысл создать базу данных сразу после установки на устройство.

  • У нас уже есть начальная база данных

Рассмотрим первую ситуацию. Для этого в конструкторе контекста мы генерируем базу данных, которая соответствует определению моделей, с помощью выражения Database.EnsureCreated().

И в завершении изменим код файла App.xaml.cs, чтобы при запуске приложения создавалась новая база данных по этим миграциям:

using Microsoft.EntityFrameworkCore;

sealed partial class App : Application
{
    public App()
    {
        this.InitializeComponent();
        this.Suspending += OnSuspending;

        using (var db = new MobileContext())
        {
            db.Database.Migrate();
        }
	}
	
	// остальное содержимое класса App без изменений
}

В данном случае изменяется только конструктор класса App, в котором вызывается метод db.Database.Migrate() применяющий ранее созданные миграции.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850