在ASP.NET Core SignalR中管理DbContext生存期

时间:2019-04-23 06:10:16

标签: 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 个答案:

答案 0 :(得分:0)

在第一种方法中,DbContext同时在操作之间共享,这会导致错误和意外结果。为了避免在第二种方法中每次创建和处理DbContextDbContextPooling可以提高性能。

可以创建可重用实例池。它不处理实例,而是返回池并将实例重置为其默认状态。因此,该代码将首先检查池中是否有可用实例,而不是每次都创建一个新实例。

您可以在DbContextPooling类的Configure方法中启用startup

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

默认池大小值为128。有关更多信息,请阅读this article