Использование одноэлементного DbContext вызывает проблемы с подключением в многопоточной среде

Я использую SQLCipher для шифрования БД sqlite в приложении WPF. Согласно знаниям, они рекомендуют использовать шаблон Singleton для моего класса DbContext, чтобы обеспечить использование одного экземпляра во всем моем приложении для повышения производительности. Ниже приведена упрощенная версия кода:

public class MyDbContext : DbContext
{
    private static MyDbContext _instance;

    private MyDbContext() : base("MyConnectionString") { }

    public static MyDbContext Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new MyDbContext();
            }
            return _instance;
        }
    }
}

Для операций удаления, обновления и вставки я начинаю транзакцию и выполняю операции. Однако иногда я выполняю операции сохранения и обновления из отдельного потока. Проблема возникает, когда один поток выполняет операцию обновления, а основной поток одновременно пытается прочитать данные из базы данных. Это вызывает следующее исключение:

Error occurred while reading from the store provider's data reader. See the inner exception for details.
---> System.InvalidOperationException: Connection was closed, statement was terminated
at System.Data.SQLite.SQLiteDataReader.CheckClosed()
at System.Data.SQLite.SQLiteDataReader.PrivateRead(Boolean ignoreSingleRow)
at System.Data.SQLite.SQLiteDataReader.Read()

Мои вопросы:

  1. как изящно избежать таких ошибок?
  2. Будет ли уместна реализация логики повтора при получении исключения с задержкой?
  3. Любое другое предложение решения.

Любая помощь или руководство будут оценены по достоинству!

«Насколько мне известно, они рекомендуют использовать шаблон Singleton для моего класса DbContext». Не могли бы вы добавить ссылку на эту рекомендацию?

Theodor Zoulias 15.08.2024 17:45

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

Devon Bessemer 15.08.2024 19:51

Я бы порекомендовал эту статью: Learn.microsoft.com/en-us/ef/core/dbcontext-configuration.

ojonasplima 16.08.2024 02:02

«Любая помощь или руководство будут оценены!» - Да: ты делаешь это совершенно неправильно. DbContext должен быть недолговечным объектом единицы работы , который не разделяется между потоками. Одноэлементный DbContext неверен, это просто и ясно. (Кстати, EF6 и EFCore в этом отношении идентичны).

Dai 16.08.2024 09:49
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Согласно знаниям, они рекомендуют использовать шаблон Singleton для моего класса DbContext, чтобы обеспечить использование одного экземпляра во всем моем приложении для повышения производительности.

Это знание на 100% неверно и на 100% является причиной всех ваших проблем; где бы вы ни нашли этот совет: возможно, переоцените, насколько вы доверяете оттуда! Они могут ошибаться только в одной теме, или они могут ошибаться во многих темах, или, может быть, это просто пробел в общении, и то, что они пытаются сообщить, не совсем так, как вы это интерпретировали.

Не делай этого.

  • DbContext рассчитан на кратковременный срок службы; вы, конечно, не хотите, чтобы со временем накапливались корзины известных сущностей
  • эти сегменты известных сущностей сами по себе не предназначены для одновременного использования, и любые операции, которые взаимодействуют с ними одновременно (особенно, когда хотя бы одна параллельная операция является мутацией): не определено
  • базовое соединение, вероятно, является соединением ADO.NET, которое не является потокобезопасным API, и если параллельные базовые операции с данными в конечном итоге происходят одновременно: undefined

Короче говоря: используйте DbContext таким образом, чтобы a: ограничивался конкретной операцией (или набором связанных операций), а b: не разрешал одновременный доступ.

Другие вопросы по теме