我想在数据库中存储完整的国际象棋游戏,以支持用户观看重播。
到目前为止,我有一个单例GameManager
,用于存储所有正在进行的游戏。因此,在startup.cs
中,我有以下代码行:
services.AddSingleton<IBattleManager, BattleManager>();
现在,我想让BattleManager
访问DbContext
来保存完成的游戏。
public class BattleManager : IBattleManager
{
//...
private void EndGame(ulong gameId)
{
var DbContext = WhatDoIPutHere?
lock(gameDictionary[gameId])
{
DbContext.Replays.Add(new ReplayModel(gameDictionary[gameId]));
gameDictionary.Remove(gameId)
}
}
}
是否有可能实现这一目标?怎么样?
尝试失败:
public class BattleManager : IBattleManager
{
Data.ApplicationDbContext _context;
public BattleManager(Data.ApplicationDbContext context)
{
_context = context;
}
}
这显然将失败,因为无法像这样将EF Core DbContext
注入到Singleton服务中。
我有一种模糊的感觉,我应该做这种事情:
using (var scope = WhatDoIPutHere.CreateScope())
{
var DbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
DbContext.Replays.Add(new ReplayModel(...));
}
这是正确的方向吗?
答案 0 :(得分:3)
您在正确的轨道上。 IServiceScopeFactory
可以做到。
public class BattleManager : IBattleManager {
private readonly IServiceScopeFactory scopeFactory;
public BattleManager(IServiceScopeFactory scopeFactory)
{
this.scopeFactory = scopeFactory;
}
public void MyMethod() {
using(var scope = scopeFactory.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<DbContext>();
// when we exit the using block,
// the IServiceScope will dispose itself
// and dispose all of the services that it resolved.
}
}
}
DbContext
的行为就像在该Transient
语句中具有using
范围一样。