在 ASP.NET Core SignalR 中管理 DbContext 生命周期
Managing DbContext lifetime in ASP.NET Core SignalR
我已经实现了一个 ASP.Core SignalR 应用程序。
共享集线器 class 每 10 秒向其所有客户端调用一个信号
来自 class SharedHub
(这个 class 不是继承自 Hub
它有逻辑让 IHubContext
调用)
public void Tick(){
var time = _context.table.time;
invoke('tick', time.tick);
}
同样在class一旦一个新的连接建立了一个调用更新数据库的方法
public void UpdateSocketConnection(int connectionId){
var connection =_context.connection;
connection.id = connectionId;
_context.saveChanges();
}
此实现的问题在于连接当前正在调用 Tick()
方法并且同时连接了一个客户端。 _context
抛出错误提示:
_context in use.
(我会在重现后更新确切的错误消息)。
我做了什么?
我已经实现了一个工厂方法来在每个方法
之上获取_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
可以提高性能。
可以创建可重用实例池。它没有释放实例,而是 returns 到池中并将实例重置为默认状态。因此,代码不会每次都创建一个新实例,而是首先检查池中是否有可用实例。
您可以在 startup
中的 Configure
方法中启用 DbContextPooling
class:
services.AddDbContextPool<YourContext>(options => options.UseSqlServer(connection));
默认池大小值为 128。阅读 this article 了解更多信息。
我已经实现了一个 ASP.Core SignalR 应用程序。
共享集线器 class 每 10 秒向其所有客户端调用一个信号
来自 class SharedHub
(这个 class 不是继承自 Hub
它有逻辑让 IHubContext
调用)
public void Tick(){
var time = _context.table.time;
invoke('tick', time.tick);
}
同样在class一旦一个新的连接建立了一个调用更新数据库的方法
public void UpdateSocketConnection(int connectionId){
var connection =_context.connection;
connection.id = connectionId;
_context.saveChanges();
}
此实现的问题在于连接当前正在调用 Tick()
方法并且同时连接了一个客户端。 _context
抛出错误提示:
_context in use.
(我会在重现后更新确切的错误消息)。
我做了什么?
我已经实现了一个工厂方法来在每个方法
之上获取_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
可以提高性能。
可以创建可重用实例池。它没有释放实例,而是 returns 到池中并将实例重置为默认状态。因此,代码不会每次都创建一个新实例,而是首先检查池中是否有可用实例。
您可以在 startup
中的 Configure
方法中启用 DbContextPooling
class:
services.AddDbContextPool<YourContext>(options => options.UseSqlServer(connection));
默认池大小值为 128。阅读 this article 了解更多信息。