SignalR和数据库上下文处理

问题描述 投票:1回答:1

我一直在尝试让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;
    }
}

但它仍然感觉很浪费,因为我不断地做同样的事情,当一个用户正在进行多次通话时它会加起来,所以在我继续之前想知道我是否正在沿着错误的路线行驶,如果是这样的话路线我应该服用。

谢谢

c# database signalr
1个回答
1
投票

您的代码应如下所示

// 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语句来完成。

© www.soinside.com 2019 - 2024. All rights reserved.