Кажется, мы получаем слишком много исключений из-за повреждения базы данных в нашем приложении 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 . Где сказано следующее:
Общий кэш по умолчанию отключен. Рекомендуется, чтобы так и оставалось. Другими словами, не используйте эту процедуру. Этот интерфейс по-прежнему предоставляется для исторической совместимости, но его использование не рекомендуется.
Кто-нибудь знает что-нибудь об этом?