我已经实现了ASP.Core SignalR应用程序。
共享集线器类每隔10秒从类SharedHub
向其所有客户端调用一个信号(此类不是从Hub
继承的,它具有使IHubContext
调用的逻辑)
public void Tick(){
var time = _context.table.time;
invoke('tick', time.tick);
}
同样在同一个类中,一个新连接建立了一个名为update database的方法
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();
}
这实际上解决了这个问题。但这似乎不是正确的做法。每次在每个方法的基础上获取新的上下文时,我不确定性能。这似乎是不好的做法。
我想知道这种情况可能的实现方式。
在第一种方法中,DbContext
同时在操作之间共享,并导致错误和意外结果。为避免每次在第二种方法中创建和处置DbContext
,DbContextPooling
可以帮助提高性能。
可以创建可重用实例池。它不是处理实例,而是返回池并将实例重置为其默认状态。因此,代码不是每次都创建一个新实例,而是首先检查池中是否有可用的实例。
您可以在DbContextPooling
类中的Configure
方法中启用startup
:
services.AddDbContextPool<YourContext>(options => options.UseSqlServer(connection));
默认池大小值为128.有关详细信息,请阅读this article。