Я создал файл questions.db с помощью DB Browser.
Вот он: Мой прекрасный файл .db
Я хочу добавить его в решение Xamarin.Forms и прочитать из него данные. (Это будет приложение-викторина)
Звучит довольно просто, верно, но я часами гуглю. Большинство ответов просто ссылаются на этот https:// Learn.microsoft.com/en-us/xamarin/xamarin-forms/data-cloud/data/databases
Что ничего не объясняет о файле базы данных, созданном вручную, о том, куда его поместить и т. д.
РЕДАКТИРОВАТЬ: это то, чего я пытаюсь достичь: https://arteksoftware.com/deploying-a-database-file-with-a-xamarin-forms-app/
К сожалению, руководство устарело, и многое в нем не работает.
Итак, куда мне поместить мой файл .db? В ресурсах и ресурсах MyApp.Android для MyApp.iOS? Если да, то как мне получить строку DBpath для нового подключения?
_database = new SQLiteAsyncConnection(dbPath);
1 ответ
Если вы хотите сделать следующее:
Добавьте в свой проект уже существующую базу данных и загрузите эту базу данных для использования вашим приложением, а затем продолжите чтение.
Короткий ответ
Вам нужно добавить файл базы данных в определенную папку в проекте paltform (Assets в Android, в iOS вы можете просто создать папку и поместите туда файл) и используйте DependencyService для доступа к нему. Скопируйте файл базы данных куда-нибудь на свое устройство (папка данных приложения или InternalStorage или любой другой вариант разрешены на каждой платформе) и используйте этот окончательный путь в конструкторе SQLite. Отныне вы можете просто использовать это соединение SQLite, как и любое другое, для выполнения операции CRUD в вашей базе данных.
Длинный ответ
Теперь я опишу, как добиться этого шаг за шагом, от создания нового проекта Xamarin.Forms до чтения данных из предварительно загруженной базы данных.
Примечание. Следующее решение будет охватывать только часть кроссплатформенного решения Android. Расширение этого на iOS не должно быть проблемой.
Отказ от ответственности: код, представленный далее, следует рассматривать только как руководство, и я ни в коем случае не утверждаю, что он проверен или похож на производственный.
0. Подготовка проекта:
Создайте новый проект Xamarin.Forms (в моем случае я использую Visual Studio v. 16.3.8 и в новом проекте установлен Xamarin.Forms 4.2)
Затем, прежде всего, установите пакет sqlite nuget во ВСЕ ваши проекты:
1. Подготовьте базу данных
В файле App.xaml.cs
// Create db static property to perform the
// Database calls from around the project
public static Database db { get; set; }
public App()
{
InitializeComponent();
MainPage = new MainPage();
}
Создайте новый файл класса и назовите его Database.cs. Там вы открываете соединение с базой данных.
public class Database
{
// Create a SQLiteAsyncConnection property to be accessed
// publicly thru your App.
public SQLiteAsyncConnection DBInstance { get; set; }
public Database(String databasePath)
{
DBInstance = new SQLiteAsyncConnection(databasePath);
}
private async Task<string> GetDatabaseFilePath()
{
return await DependencyService.Get<IPathFinder>().GetDBPath();
}
}
Пока все хорошо, но... Каким на самом деле должен быть путь к вашей предварительно загруженной базе данных? Ну, это следующая часть.
2. Загрузите уже существующую базу данных в свой проект и получите путь к ней (Android)
Таким образом, большой вопрос заключается в том, где хранить уже существующую базу данных в проекте.
Один из вариантов — добавить его в качестве актива. Чтобы реализовать этот подход, сделайте следующее:
2.1 Добавить файл базы данных в папку Assets в проекте Android
Теперь мы хотим получить доступ к этой базе данных. Для этого выполните следующие действия:
2.2 Создайте интерфейс IPathFinder в своем проекте приложения
И там определите один элемент GetDBPath()
public interface IPathFinder
{
Task<String> GetDBPath();
}
Теперь в вашем проекте Android создайте файл класса PathFinder.cs для реализации этого интерфейса.
И реализуйте метод (обратите внимание на атрибут зависимости над пространством имен!)
using System;
using SysIO = System.IO;
using System.Threading.Tasks;
using Java.IO;
using Xamarin.Forms;
using TestDB.Droid;
[assembly: Dependency(typeof(PathFinder))]
namespace TestDB.Droid
{
public class PathFinder : IPathFinder
{
public async Task<string> GetDBPath()
{
String dbPath = String.Empty;
if (await PermissonManager.GetPermission(PermissonManager.PermissionsIdentifier.Storage))
{
String systemPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.RootDirectory.Path).Path;
String tempFolderPath = SysIO::Path.Combine(systemPath, "MytestDBFolder");
if (!SysIO::File.Exists(tempFolderPath))
{
new File(tempFolderPath).Mkdirs();
}
dbPath = SysIO::Path.Combine(tempFolderPath, "test.db");
if (!SysIO::File.Exists(dbPath))
{
Byte[] dbArray;
using (var memoryStream = new SysIO::MemoryStream())
{
var dbAsset = MainActivity.assets.Open("test.db");
dbAsset.CopyTo(memoryStream);
dbArray = memoryStream.ToArray();
}
SysIO.File.WriteAllBytes(dbPath, dbArray);
}
}
return dbPath;
}
}
}
В методе GetDBPath() первым следует отметить метод GetPermission. Это необходимо, начиная с Android API 23, для управления разрешениями приложений.
Создайте файл с именем PermissonManager в вашем проекте Android.
И добавьте код ниже
using System;
using System.Threading.Tasks;
using Android;
using Android.App;
using Android.Content.PM;
using Android.OS;
using Android.Support.V4.App;
namespace TestDB.Droid
{
public class PermissonManager
{
public enum PermissionsIdentifier
{
Storage // Here you can add more identifiers.
}
private static String[] GetPermissionsRequired(PermissionsIdentifier identifier)
{
String[] permissions = null;
if (identifier == PermissionsIdentifier.Storage)
permissions = PermissionExternalStorage;
return permissions;
}
private static Int32 GetRequestId(PermissionsIdentifier identifier)
{
Int32 requestId = -1;
if (identifier == PermissionsIdentifier.Storage)
requestId = ExternalStorageRequestId;
return requestId;
}
public static TaskCompletionSource<Boolean> PermissionTCS;
public static readonly String[] PermissionExternalStorage = new String[] { Manifest.Permission.ReadExternalStorage, Manifest.Permission.WriteExternalStorage };
public const Int32 ExternalStorageRequestId = 2;
public static async Task<Boolean> GetPermission(PermissionsIdentifier identifier)
{
Boolean isPermitted = false;
if ((Int32)Build.VERSION.SdkInt < 23)
isPermitted = true;
else
isPermitted = await GetPermissionOnSdk23OrAbove(GetPermissionsRequired(identifier), GetRequestId(identifier));
return isPermitted;
}
private static Task<Boolean> GetPermissionOnSdk23OrAbove(String[] permissions, Int32 requestId)
{
PermissionTCS = new TaskCompletionSource<Boolean>();
if (MainApplication.CurrentContext.CheckSelfPermission(permissions[0]) == (Int32)Permission.Granted)
PermissionTCS.SetResult(true);
else
ActivityCompat.RequestPermissions((Activity)MainApplication.CurrentContext, permissions, requestId);
return PermissionTCS.Task;
}
public static void OnRequestPermissionsResult(Permission[] grantResults)
{
PermissionTCS.SetResult(grantResults[0] == Permission.Granted);
}
}
}
В этом классе вы заметите наличие MainApplication, который предоставляет CurrentContext. Вам также нужно будет добавить этот файл класса
И добавьте следующий код
using System;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
namespace DemoDB.Droid
{
[Application]
public partial class MainApplication : Application, Application.IActivityLifecycleCallbacks
{
private static Context _currentContext = Application.Context;
internal static Context CurrentContext
{
get => _currentContext;
private set
{
_currentContext = value;
}
}
internal static String FileProviderAuthority
{
get => MainApplication.CurrentContext.ApplicationContext.PackageName + ".fileprovider";
}
public MainApplication(IntPtr handle, JniHandleOwnership transfer) : base(handle, transfer)
{
}
public override void OnCreate()
{
base.OnCreate();
RegisterActivityLifecycleCallbacks(this);
}
public override void OnTerminate()
{
base.OnTerminate();
UnregisterActivityLifecycleCallbacks(this);
}
public void OnActivityCreated(Activity activity, Bundle savedInstanceState)
{
CurrentContext = activity;
}
public void OnActivityDestroyed(Activity activity)
{
}
public void OnActivityPaused(Activity activity)
{
}
public void OnActivityResumed(Activity activity)
{
CurrentContext = activity;
}
public void OnActivitySaveInstanceState(Activity activity, Bundle outState)
{
}
public void OnActivityStarted(Activity activity)
{
CurrentContext = activity;
}
public void OnActivityStopped(Activity activity)
{
}
}
}
Теперь ваш PermissonManager почти готов. Теперь вам просто нужно переопределить OnRequestPermissionsResult
в файле MainActivity.
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
PermissonManager.OnRequestPermissionsResult(grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
Возвращаясь к методу GetPath(), вы видите таинственный вызов свойства MainActivity.assets. Это должно быть создано в MainActivity следующим образом
public static AssetManager assets;
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
assets = this.Assets;
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
Почти готов! Теперь вы просто вызываете свою базу данных.
3. Используйте свою базу данных!
Из OnAppearing главной страницы сделайте простой вызов базы данных, чтобы создать ее и получить к ней доступ.
protected override async void OnAppearing()
{
String databasePath = await Database.GetDatabaseFilePath();
App.db = new Database(databasePath);
var table = await App.db.DBInstance.CreateTableAsync<Category>();
// here Category is a class that models the objects
// present in my pre-existent database
List<Category> categories = new List<Category>();
categories = await App.db.DBInstance.Table<Category>().ToListAsync();
base.OnAppearing();
}
Вот и все.
Я надеюсь, что это полезно: P
Похожие вопросы
Связанные вопросы
Новые вопросы
sql
Язык структурированных запросов (SQL) - это язык запросов к базам данных. Вопросы должны включать примеры кода, структуру таблицы, примеры данных и тег для используемой реализации СУБД (например, MySQL, PostgreSQL, Oracle, MS SQL Server, IBM DB2 и т. Д.). Если ваш вопрос относится исключительно к конкретной СУБД (использует определенные расширения / функции), используйте вместо этого тег этой СУБД. Ответы на вопросы, помеченные SQL, должны использовать стандарт ISO / IEC SQL.
NSBundle.MainBundle.PathForResource("MyLite", "db");
должен дать вам путь к ресурсам. Обратите внимание, что файлы в пакете приложений доступны только для чтения.