Xamarin: приложение с двумя локальными базами данных SQLite и Linq

#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, независимо от того, что может делать само приложение. Кажется, было бы просто протестировать чтение и запись из двух разных баз данных, чтобы убедиться, что они независимы друг от друга