Подключение к существующей базе данных

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

В прошлой теме мы подключались к базе данных SQLite, которая автоматически создавалась (при ее отсутствии) при запуске приложения. Однако это не всегда бывает удобно. Иногда необходимо, чтобы к первому запуску приложения база данных уже имела некоторые начальные данные, которые мы тут же можем использовать. Поэтому рассмотрим, как мы можем добавить в проект уже имеющуюся базу данных SQLite и использовать ее.

Вначале создадим саму базу данных. Для работы с SQLite установим специальный инструмент - DB Browser for SQLite.

Откроем DB Browser for SQLite и для создания новой базы данных нажмем на кнопку New Database. В открывшемся окне выберем место расположения файла базы данных и укажем для нее имя, например, friends5.

Далее нам будет предложено добавить в базу данных таблицы. Возьмем проект из прошлой темы. В нем была модель Friend:

using SQLite;

namespace HelloApp
{
    [Table("Friends")]
    public class Friend
    {
        [PrimaryKey, AutoIncrement, Column("_id")]
        public int Id { get; set; }

        public string Name { get; set; }
        public string Email { get; set; }
        public string Phone { get; set; }
    }
}

Для хранения объектов данной модели определим в базе данных новую таблицу Users и добавим четыре столбца _id, Name, Email, Phone, как на скриншоте::

Создание базы данных SQLite для Xamarin Forms

Эта таблица имеет столбцы, которые соответствуют свойствам класса Friend.

Можно тут же добавить некоторые начальные данные в таблицу.

базы данных SQLite для Xamarin Forms

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

После создания базы данных добавим ее в главный проект решения и установим в окне Properties (Свойства) у файла базы данных в поле Build Action значение Embedded Resource:

Добавление базы данных SQLite для Xamarin Android

Далее откроем файл App.xaml.cs и определим логику копирования базы данных:

using System;
using System.IO;
using Xamarin.Forms;
using System.Reflection;

namespace HelloApp
{
    public partial class App : Application
    {
        public const string DATABASE_NAME = "friends5.db";
        public static FriendAsyncRepository database;
        public static FriendAsyncRepository Database
        {
            get
            {
                if (database == null)
                {
                    // путь, по которому будет находиться база данных
                    string dbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), DATABASE_NAME);
                    // если база данных не существует (еще не скопирована)
                    if (!File.Exists(dbPath))
                    {
                        // получаем текущую сборку
                        var assembly = IntrospectionExtensions.GetTypeInfo(typeof(App)).Assembly;
                        // берем из нее ресурс базы данных и создаем из него поток
                        using (Stream stream = assembly.GetManifestResourceStream($"HelloApp.{DATABASE_NAME}"))
                        {
                            using (FileStream fs = new FileStream(dbPath, FileMode.OpenOrCreate))
                            {
                                stream.CopyTo(fs);  // копируем файл базы данных в нужное нам место
                                fs.Flush();
                            }
                        }
                    }
                    database = new FriendAsyncRepository(dbPath);
                }
                return database;
            }
        }
        public App()
        {
            InitializeComponent();

            MainPage = new NavigationPage(new MainPage());
        }
        protected override void OnStart()
        {
        }
        protected override void OnSleep()
        {
        }
        protected override void OnResume()
        {
        }
    }
}

В данном случае наша задача скопировать файл базы данных в папку . Для этого вначале получаем встроенный ресурс посредством метода assembly.GetManifestResourceStream($"HelloApp.{DATABASE_NAME}")). "HelloApp" в данном случае это название текущей сборки - по сути название проекта, соответственно если название проекта другое, то оно может изменяться.

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

При этом нам НЕ надо ничего добавлять в другие проекты или изменять их код.

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

Весь остальной код в данном случае остается тем же, что и вв прошлой теме. В частности, код репозитория - класса FriendAsyncRepository:

using System.Collections.Generic;
using System.Threading.Tasks;
using SQLite;
using Xamarin.Forms;

namespace HelloApp
{
    public class FriendAsyncRepository
    {
        SQLiteAsyncConnection database;
        
        public FriendAsyncRepository(string databasePath)
        {
            database = new SQLiteAsyncConnection(databasePath);
        }

        public async Task CreateTable()
        {
            await database.CreateTableAsync<Friend>();
        }
        public async Task<List<Friend>> GetItemsAsync()
        {
            return await database.Table<Friend>().ToListAsync();

        }
        public async Task<Friend> GetItemAsync(int id)
        {
            return await database.GetAsync<Friend>(id);
        }
        public async Task<int> DeleteItemAsync(Friend item)
        {
            return await database.DeleteAsync(item);
        }
        public async Task<int> SaveItemAsync(Friend item)
        {
            if (item.Id != 0)
            {
                await database.UpdateAsync(item);
                return item.Id;
            }
            else
            {
                return await database.InsertAsync(item);
            }
        }
    }
}

Xaml-код страницы MainPage.xaml выглядит следующим образом:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="HelloApp.MainPage" Title="Список друзей">
  <StackLayout>
    <ListView x:Name="friendsList" ItemsSource="{Binding}" ItemSelected="OnItemSelected">
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <ViewCell.View>
              <StackLayout Orientation="Horizontal">
                <Label Text="{Binding Name}" FontSize="Medium" />
              </StackLayout>
            </ViewCell.View>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>
    <Button Text="Добавить" Clicked="CreateFriend" />
  </StackLayout>
</ContentPage>

Код MainPage.xaml.cs:

using System;
using Xamarin.Forms;

namespace HelloApp
{
	public partial class MainPage : ContentPage
	{
		public MainPage()
		{
			InitializeComponent();
		}

		protected override async void OnAppearing()
		{
			// создание таблицы, если ее нет
			await App.Database.CreateTable();
			// привязка данных
			friendsList.ItemsSource = await App.Database.GetItemsAsync();
			
			base.OnAppearing();
		}
		// обработка нажатия элемента в списке
        private async void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
        {
            Friend selectedFriend = (Friend)e.SelectedItem;
            FriendPage friendPage = new FriendPage();
            friendPage.BindingContext = selectedFriend;
            await Navigation.PushAsync(friendPage);
        }
        // обработка нажатия кнопки добавления
        private async void CreateFriend(object sender, EventArgs e)
        {
            Friend friend = new Friend();
            FriendPage friendPage = new FriendPage();
            friendPage.BindingContext = friend;
            await Navigation.PushAsync(friendPage);
        }
	}
}

Интерфейс страницы FriendPage.xaml для отображения одного объекта:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="HelloApp.FriendPage" Title="Информация о друге">
  <StackLayout>
    <Label Text="Имя" />
    <Entry Text="{Binding Name}" />
    <Label Text="Email" />
    <Entry Text="{Binding Email}" />
    <Label Text="Телефон" />
    <Entry Text="{Binding Phone}" />
    <StackLayout Orientation="Horizontal">
      <Button Text="Сохранить" Clicked="SaveFriend" />
      <Button Text="Удалить" Clicked="DeleteFriend" />
      <Button Text="Отмена" Clicked="Cancel" />
    </StackLayout>
  </StackLayout>
</ContentPage>

Файл связанного кода FriendPage.xaml.cs:

using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace HelloApp
{
    public partial class FriendPage : ContentPage
    {
        public FriendPage()
        {
            InitializeComponent();
        }
        private async void SaveFriend(object sender, EventArgs e)
        {
            var friend = (Friend)BindingContext;
            if (!String.IsNullOrEmpty(friend.Name))
            {
                await App.Database.SaveItemAsync(friend);
            }
            await this.Navigation.PopAsync();
        }
        private async void DeleteFriend(object sender, EventArgs e)
        {
            var friend = (Friend)BindingContext;
            await App.Database.DeleteItemAsync(friend);
            await this.Navigation.PopAsync();
        }
        private async void Cancel(object sender, EventArgs e)
        {
            await this.Navigation.PopAsync();
        }
    }
}
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850