#android #ios #sqlite #xamarin
#Android #iOS #sqlite #xamarin
Вопрос:
Я пишу простое кроссплатформенное приложение Xamarin (Android ios), и у меня есть сомнения по поводу того, как управлять SQLite в моем приложении.
Приложение имеет базу данных SQLite (main.db3), которая является основной базой данных. Я объявил класс, сопоставленный таблице базы данных main.db3 с библиотекой Sqlite-net-pcl.
Приложение должно периодически загружать с удаленного сервера другой файл db3, содержащий разницу между локальной базой данных main.db3 и базой данных, которая находится на удаленном сервере. Итак, приложение загружает этот файл delta.db3, берет содержащиеся в нем записи и помещает их, объединяя с уже содержащимися записями, в основную базу данных.db3.
Для доступа к delta.db3 я использую те же классы, которые я сопоставил с базой данных main.db3, потому что таблицы абсолютно одинаковы: единственное, что меняется с delta.db3 на main.db3, — это данные, содержащиеся в них.
Я инициализирую подключение к базе данных main.db3 следующим образом:
public class MainDb {
public const SQLite.SQLiteOpenFlags Flags = SQLite.SQLiteOpenFlags.ReadWrite |
SQLite.SQLiteOpenFlags.Create |
SQLite.SQLiteOpenFlags.SharedCache;
static SQLiteAsyncConnection Database;
public MainDb()
{
Database = new SQLiteAsyncConnection(MainDb.GetDbFilePath(), MainDb.Flags);
if (!Database.TableMappings.Any(m => m.MappedType.Name == typeof(MyEntityModel).Name))
{
Database.CreateTablesAsync(CreateFlags.None, typeof(MyEntityModel)).Wait();
}
}
...
}
И я инициализирую совместное подключение к базе данных delta.db3 следующим образом:
public class DeltaDb
{
public const SQLite.SQLiteOpenFlags Flags = SQLite.SQLiteOpenFlags.ReadWrite |
SQLite.SQLiteOpenFlags.SharedCache;
static SQLiteAsyncConnection Database;
public DeltaDb()
{
Database = new SQLiteAsyncConnection(DeltaDb.GetDbFilePath(), DeltaDb.Flags);
if (!Database.TableMappings.Any(m => m.MappedType.Name == typeof(MyEntityModel).Name))
{
Task<CreateTablesResult> result = Database.CreateTablesAsync(CreateFlags.None, typeof(MyEntityModel));
result.Wait();
}
}
...
}
Проблема в том, что при первом запуске приложения не создается main.db3, потому что оно будет создано путем создания пустой базы данных main.db3, а затем заполнения ее данными из delta.db3, и после создания соединения delta.db3 вызывается конструктор MainDb и строка
if (!Database.TableMappings.Any(m => m.MappedType.Name == typeof(MyEntityModel).Name)) { ... }
предотвращает строку
Database.CreateTablesAsync(CreateFlags.None, typeof(MyEntityModel)).Wait();
после выполнения таблица в базе данных main.db3 не создается. Итак, intert () в main.db3 завершается с ошибкой, сообщающей, что таблица не существует.
Я заметил, что, в некотором роде, сопоставления (база данных.Табличные приложения) уже есть, как будто открытие соединения с delta.db3 произвело некоторое «глобальное» сопоставление для всего приложения.
Итак, вопрос в том, как я могу этого избежать? Наверняка я делаю что-то не так с инициализацией подключений к двум разным базам данных sqlite в одном приложении, но я не могу найти никакой документации, которая дала бы мне подсказку о том, как я могу сделать это правильно.
Это мое первое приложение Xamarin, и я два дня гуглил, прежде чем решил задать вопрос здесь.
Спасибо.
РЕДАКТИРОВАТЬ: я нашел ту статью, которую забыл упомянуть. Но я не знаю, актуально ли оно по-прежнему. https://ericsink.com/entries/multiple_sqlite_problem.html
Комментарии:
1. зачем вам нужна проверка перед
CreateTablesAsync
? Этот метод не должен перезаписывать какие-либо существующие таблицы, поэтому его должно быть безопасно вызывать, если ваши таблицы уже существуют.2. Это то же самое, о чем я думал, но тот факт, что сопоставления уже есть, заставляет меня задуматься, не случилось ли чего-нибудь в том, как я инициализирую dbs. Не должны ли табличные приложения для main.db3 быть пустыми при первом открытии соединения? Зачем они там? Являются ли они результатом открытия соединения с delta.db3? Меня это сбивает с толку… И мне интересно, может ли это привести к проблемам, потому что мои знания ограничены, и я не нахожу документации об использовании двух файлов sqlite в одном приложении.
3. Я бы ожидал, что сопоставления будут пустыми — но если это то, что вы тестируете неоднократно, вы уверены, что не просто видите старую копию MainDB из предыдущего теста? AFAIK, не должно быть проблем с подключением к нескольким базам данных в одном приложении.
4. Я дважды проверил, кажется, что свойство «TableMappings» является глобальным для всех подключений SQLite… Итак, я думаю, что если у меня есть класс, сопоставленный двум разным базам данных, это может привести к проблемам, даже если я не знаю, какого рода. Я действительно хотел бы узнать об этом больше. Мне просто интересно, как можно безопасно использовать две локальные базы данных sqlite в одном приложении. Кто-нибудь делал это и у кого есть опыт в этом?
5. многие приложения используют несколько баз данных — множество плагинов используют свое собственное локальное соединение с SQLite, независимо от того, что может делать само приложение. Кажется, было бы просто протестировать чтение и запись из двух разных баз данных, чтобы убедиться, что они независимы друг от друга