Повреждение базы данных SQLite в приложении Xamarin Forms (только iOS) - PullRequest
0 голосов
/ 03 марта 2020

Кажется, мы получаем слишком много исключений из-за повреждения базы данных в нашем приложении Xamarin Forms, зарегистрированном в AppCenter для iOS. Мы придерживались очень близких к рекомендуемым шаблонам в соответствии с MSDN, поэтому я не уверен, в чем именно может быть проблема.

Чтобы дать представление о нашей реализации:

У нас есть интерфейс ISQLite, реализованный в каждом мобильная платформа с методом GetConnection:

public SQLiteConnection GetConnection()
{
  SQLiteConnection cnn = new
  SQLiteConnection(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal),
  Strings.DATABASE_NAME), SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | 
  SQLiteOpenFlags.SharedCache);
  cnn.EnableWriteAheadLogging();
  return cnn;
}

DataService.cs Lazy загружает соединение во время построения:

sqliteConn = new Lazy(() => (sqlite ?? DependencyService.Get<ISQLite>(DependencyFetchTarget.NewInstance))?.GetConnection());

, затем класс DataService блокирует ВСЕ операции с базой данных следующим образом:

public long Insert<T>(IModel model) where T : IModel, new()
{
    lock (locker)
    {
        if (model == null || sqliteConn.Value.Insert((T)model) <= 0)
            return -1;

        // Retrieve the ID of the row we just inserted
        SQLiteCommand cmd = new SQLiteCommand(sqliteConn.Value)
        {
            CommandText = "SELECT last_insert_rowid();"
        };
        return cmd.ExecuteScalar<long>();
    }
}

У нас только одно соединение, и DataService может вызываться из асинхронного кода. Мы никогда не сталкивались с какими-либо проблемами во время тестирования, но мы видим, что я чувствую слишком много этих поврежденных исключений в AppCenter.

PreparedSqlLiteInsertCommand.ExecuteNonQuery (System.Object [] source) System.Exception : Corrupt

Я что-то упускаю из виду?

ОБНОВЛЕНИЕ: Мне интересно, может ли быть проблема с флагом SQLiteOpenFlags.SharedCache. Он был добавлен после прочтения этой статьи: Xamarin: эффективное использование базы данных SQLite . Там автор пишет, что Shared Cache:

Позволяет многопоточный доступ к базе данных

Далее указывает на документацию, которая гласит:

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

Мне показалось, что это хорошо, но после дальнейшего изучения я также обнаружил следующее: Включить или отключить Shared Pager Cache . Где сказано следующее:

Общий кэш по умолчанию отключен. Рекомендуется, чтобы так и оставалось. Другими словами, не используйте эту процедуру. Этот интерфейс по-прежнему предоставляется для исторической совместимости, но его использование не рекомендуется.

Кто-нибудь знает что-нибудь об этом?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...