我已经实现了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();
}
这实际上解决了问题。但这似乎不正确。我不确定每次使用每种方法都获得新上下文时的性能。这似乎是不好的做法。
我想知道这种情况下可能的实现方式。
答案 0 :(得分:0)
在第一种方法中,DbContext
同时在操作之间共享,这会导致错误和意外结果。为了避免在第二种方法中每次创建和处理DbContext
,DbContextPooling
可以提高性能。
可以创建可重用实例池。它不处理实例,而是返回池并将实例重置为其默认状态。因此,该代码将首先检查池中是否有可用实例,而不是每次都创建一个新实例。
您可以在DbContextPooling
类的Configure
方法中启用startup
:
services.AddDbContextPool<YourContext>(options => options.UseSqlServer(connection));
默认池大小值为128。有关更多信息,请阅读this article。