Управление временем жизни DbContext в ASP.NET Core SignalR - PullRequest
0 голосов
/ 23 апреля 2019

Я реализовал приложение 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 Ответ

0 голосов
/ 23 апреля 2019

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

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

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

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

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

...