无法在 SignalR Hub 中调用 AppDbContext

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

为什么我无法在 SignalR Hub 中使用

AppDbContext
?查询本身没有任何问题。它在集线器上下文之外工作。
email
正确解析。

System.NullReferenceException:对象引用未设置到对象的实例。 在 lambda_method1325(闭包,QueryContext) 在 Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](表达式查询,CancellationToken cancellationToken) 在 Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)

我的整个想法是每当用户登录时,将所有未送达的消息发送给他。或者也许我不应该这样做?也许前端应该调用一个端点,该端点最初将从发件箱表加载这些未传递的消息,而不是 OnConnectedAsync?

[Authorize(AuthenticationSchemes = IdentityServerAuthenticationDefaults.AuthenticationScheme)]
public sealed class SignalRHub : Hub
{
    readonly ILogger<SignalRHub> _logger;
    readonly IMediator _mediator;

    public SignalRHub(ILogger<SignalRHub> logger, IMediator mediator)
    {
        _logger = logger;
        _mediator = mediator;
    }

    public override async Task OnConnectedAsync()
    {
        var email = Context.User.GetEmailAddress();
        
        await SendUndeliveredNotificationsAsync(email);

        await base.OnConnectedAsync();
    }

    async Task SendUndeliveredNotificationsAsync(string email)
    {
        var undeliveredNotifications = await _mediator.Send(new GetUndeliveredNotificationsForUserQuery(email));
        var tasks = undeliveredNotifications.Select(notificationMessage => _mediator.Send(new SendInAppNotificationCommand(notificationMessage.Id)));
        await Task.WhenAll(tasks);
    }
}

public sealed record GetUndeliveredNotificationsForUserQuery(string Email) : IRequest<IReadOnlyCollection<NotificationMessage>>;

public sealed class GetUndeliveredNotificationsForUserQueryHandler : IRequestHandler<GetUndeliveredNotificationsForUserQuery, IReadOnlyCollection<NotificationMessage>>
{
    readonly AppDbContext _dbContext;

    public GetUndeliveredNotificationsForUserQueryHandler(AppDbContext dbContext) => _dbContext = dbContext;

    public async Task<IReadOnlyCollection<NotificationMessage>> Handle(GetUndeliveredNotificationsForUserQuery request, CancellationToken cancellationToken)
        => await _dbContext.NotificationMessages
            .AsNoTracking()
            .Include(x => x.Notification)
            .ThenInclude(x => x.Employee)
            .Where(x => x.Notification.Employee != null && x.Notification.Employee.Email == request.Email && x.DateDelivered == null)
            .ToListAsync(cancellationToken);
}

c# asp.net-core signalr signalr-hub
1个回答
1
投票

问题解决了!

尽管索赔已从

AuthorizeAttribute
解决,但租户 ID 本身并未设置。

这就是我最终做的。重要的是

_dbContext.TenancyContext.Tenant = applicationTenant;

[Authorize(AuthenticationSchemes = IdentityServerAuthenticationDefaults.AuthenticationScheme)]
public sealed class SignalRHub : Hub
{
    readonly ILogger<SignalRHub> _logger;
    readonly AppDbContext _dbContext;

    public SignalRHub(ILogger<SignalRHub> logger, AppDbContext dbContext)
    {
        _logger = logger;
        _dbContext = dbContext;
    }

    ...

    public async Task GetUndeliveredMessages()
    {
        var email = Context.User.GetEmailAddress();
        var tenant = Context.User.GetTenant();
        
        var applicationTenant = await _dbContext.Tenants.AsNoTracking().FirstOrDefaultAsync(x => x.NormalizedCanonicalName == tenant);
        
        _dbContext.TenancyContext.Tenant = applicationTenant;
        
        var undeliveredMessages = await _dbContext.NotificationMessages
            .AsNoTracking()
            .Include(x => x.Notification)
            .ThenInclude(x => x.Employee)
            .Where(x => x.Notification.Employee != null && x.Notification.Employee.Email == email && x.ChannelType == ChannelType.InApp && x.DateDelivered == null)
            .Select(x => x.MapToResponse())
            .ToListAsync();
            
        await Clients.Caller.SendAsync("ReceiveUndeliveredMessages", undeliveredMessages);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.