Управление временем жизни DbContext в ASP.NET Core SignalR

#c# #asp.net-core #signalr

#c# #asp.net-core #signalr

Вопрос:

Я внедрил ASP.Приложение Core SignalR.

Общий класс-концентратор каждые 10 секунд отправляет сигнал всем своим клиентам из класса SharedHub (этот класс не наследуется от Hub него есть логика, которую нужно получить IHubContext для вызова)

 public void Tick(){
    var time = _context.table.time;
    invoke('tick', time.tick);
}
  

Также в том же классе, как только новое соединение установлено, вызывается метод для обновления базы данных

 public void UpdateSocketConnection(int connectionId){
    var connection =_context.connection;
    connection.id = connectionId;
    _context.saveChanges();
}
  

Проблема с этой реализацией заключается в том, что в данный момент соединение вызывает Tick() метод, а также клиент, подключенный одновременно. _context выдает ошибку со словами:

_context используется.

(Я обновлю точное сообщение об ошибке, как только воспроизведу).

Что я сделал?

Я внедрил заводской метод для получения нового экземпляра _context поверх каждого метода

 public void Tick(){
    var time = factory.GetContext().time;
    invoke('tick', time.tick);
}

public void UpdateSocketConnection(int connectionId){
    var context = Factory.getContext();

    var connection =context.connection;
    connection.id = connectionId;
    context .saveChanges();
}
  

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

Я хочу знать, какова возможная реализация для этого сценария.

Комментарии:

1. не могли бы вы показать объявление хаба и инициализацию _context ?

Ответ №1:

В первом подходе DbContext разделяется между операциями одновременно, и это приводит к ошибке и неожиданному результату. Чтобы избежать создания и удаления DbContext каждый раз во втором подходе, DbContextPooling это может повысить производительность.

Может быть создан пул повторно используемых экземпляров. Вместо удаления экземпляра он возвращается в пул и сбрасывает экземпляр в состояние по умолчанию. Таким образом, вместо того, чтобы каждый раз создавать новый экземпляр, код сначала проверяет, есть ли экземпляр, доступный в пуле, или нет.

Вы можете включить метод DbContextPooling in Configure в startup классе:

 services.AddDbContextPool<YourContext>(options => options.UseSqlServer(connection));
  

Значение размера пула по умолчанию равно 128. Прочтите эту статью для получения дополнительной информации.