我一直在尝试让SignalR启动数据库查询,然后根据所述查询的结果响应启动它的客户端。
但我一直在遇到无法访问已处置的对象。来自DatabaseContext和HubContext。我尝试了几种不同的方法来创建一个数据库控制器单例,其中没有一个工作。
我终于设法创建了一个解决方案,但我现在想知道我是否创建了太多数据库上下文的实例/上下文。
这是我提出的方法。 (简体)
[Authorize(JwtBearerDefaults.AuthenticationScheme)]
public class Game : Hub
{
private GameContext _dbContext;
private IHubContext<Game> _hubContext;
public Game(IHubContext<Game> hubContext)
{
_hubContext = hubContext;
}
public override async Task OnConnectedAsync()
{
await Clients.Client(Context.ConnectionId).SendAsync("DebugMessage", "Connected to Hub");
await base.OnConnectedAsync();
}
public async void NewUser(string username, string userIdentifier)
{
_dbContext = new GameContext { };
string connectionID = Context.ConnectionId;
bool error = false;
bool usernameExists = false;
bool createdUser = false;
try
{
var rows = await _dbContext.Users.Where(x => x.Username == username).ToListAsync();
if (rows.Count > 0)
{
usernameExists = true;
goto SendResponse;
}
}
catch (Exception e)
{
error = true;
goto SendResponse;
}
Users user = new Users { Username = username, UserIdentifier = userIdentifier, Joined = DateTime.UtcNow };
try
{
_dbContext.Add(user);
await _dbContext.SaveChangesAsync();
createdUser = true;
goto SendResponse;
}
catch (Exception e)
{
error = true;
goto SendResponse;
}
SendResponse:
await _hubContext.Clients.Client(connectionID).SendAsync("CreatedUser", username, usernameExists, createdUser, error);
}
}
正如你在NewUser函数中看到的那样,我正在创建一个新的实例/上下文来使其工作。
感觉它是浪费的,所以在Game Hub中为它做了一个Singleton模式来检查它是否为null并在需要时创建一个新的如下。
private Object padlock = new Object { };
private GameContext _dbContextInstance;
private GameContext _dbContext
{
get
{
if (_dbContextInstance == null)
{
lock (padlock)
{
if (_dbContextInstance == null)
{
_dbContextInstance = new GameContext { };
}
}
}
return _dbContextInstance;
}
}
但它仍然感觉很浪费,因为我不断地做同样的事情,当一个用户正在进行多次通话时它会加起来,所以在我继续之前想知道我是否正在沿着错误的路线行驶,如果是这样的话路线我应该服用。
谢谢
您的代码应如下所示
// this has to be a task, otherwise the framework
// cannot know when it has finished
public async Task NewUser(string username, string userIdentifier)
{
using (var dbContext = new GameContext())
{
string connectionID = Context.ConnectionId;
bool error = false;
bool usernameExists = false;
bool createdUser = false;
try
{
usernameExists = await dbContext.Users.AnyAsync(x=> x.Username == username);
}
catch (Exception e)
{
error = true;
}
if (!usernameExists && !error)
{
Users user = new Users { Username = username, UserIdentifier = userIdentifier, Joined = DateTime.UtcNow };
try
{
dbContext.Add(user);
await dbContext.SaveChangesAsync();
createdUser = true;
}
catch (Exception e)
{
error = true;
}
}
await _hubContext.Clients.Client(connectionID).SendAsync("CreatedUser", username, usernameExists, createdUser, error);
}
}
在C#中使用标签并不常见。您应该让框架处理如何管理连接(唯一重要的事情),并通过正确使用using
语句来完成。