Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Blazor+;SQLTableDependency+;信号器:从OnChange事件通知特定组_C#_.net Core_Signalr_Blazor_Signalr Hub - Fatal编程技术网

C# Blazor+;SQLTableDependency+;信号器:从OnChange事件通知特定组

C# Blazor+;SQLTableDependency+;信号器:从OnChange事件通知特定组,c#,.net-core,signalr,blazor,signalr-hub,C#,.net Core,Signalr,Blazor,Signalr Hub,我有一个Blazor应用程序,它使用SQLTableDependency检测数据库更改,然后通过SignalR通知所有客户机更改。这是可行的,但我需要一种能够检测更改并只通知特定信号器组的方法。因为SQLTableDependency不关心是谁在数据库中插入、更改或删除了记录,所以我也不确定如何知道要发送更新的组。请参阅下面关于我的应用程序和我正在努力实现的更多详细信息 我们为每个客户建立了一个新的组织。一个组织有自己的资产列表,并且可以有多个用户 Organization.cs pub

我有一个Blazor应用程序,它使用SQLTableDependency检测数据库更改,然后通过SignalR通知所有客户机更改。这是可行的,但我需要一种能够检测更改并只通知特定信号器组的方法。因为SQLTableDependency不关心是谁在数据库中插入、更改或删除了记录,所以我也不确定如何知道要发送更新的组。请参阅下面关于我的应用程序和我正在努力实现的更多详细信息

我们为每个客户建立了一个新的组织。一个组织有自己的资产列表,并且可以有多个用户

Organization.cs

    public class Organization
    {
    public int OrganizationId { get; set; }

    public string OrganizationName { get; set; }

    public List<Asset> Assets { get; set; }

    public List<ApplicationUser> Users { get; set; }

    public bool IsDisabled { get; set; }

   }
public class Asset
{
    public int AssetId { get; set; }

    public string SerialNumber { get; set; }

    public int OrganizationId { get; set; }

    public virtual Organization Organization { get; set; }

    public DateTime DateAdded { get; set; }
}
ApplicationUser.cs

 public class ApplicationUser 
{
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public int OrganizationId { get; set; }

    public virtual Organization Organization { get; set; }

    public List<Connection> Connections { get; set; }

    public string Timezone { get; set; }

}
AssetService.cs

    public class AssetService : IAssetService
{
    private readonly IServiceScopeFactory _serviceScopeFactory;

    public AssetService(IServiceScopeFactory serviceScopeFactory)
    {
        _serviceScopeFactory = serviceScopeFactory;
    }
  
         public async Task<Asset> AddAssetAsync(Asset asset, string currentUserName)
    {
        try
        {
            using (var scope = _serviceScopeFactory.CreateScope())
            {
                var db = scope.ServiceProvider.GetService<DataContext>();

                if (asset.Device != null)
                {
                    db.Entry(asset.Device).State = EntityState.Modified;
                }
                asset.DateAdded = DateTime.UtcNow;
                await db.Assets.AddAsync(asset);
                await db.SaveChangesAsync();
                return asset;
            }
        }
        catch (System.Exception ex)
        {
           throw ex;
        }
    }
}
公共类资产服务:IAssetService
{
专用readonly IServiceScopeFactory\u serviceScopeFactory;
公共资产服务(IServiceScopeFactory服务ScopeFactory)
{
_serviceScopeFactory=serviceScopeFactory;
}
公共异步任务AddAssetAsync(资产,字符串currentUserName)
{
尝试
{
使用(var scope=\u serviceScopeFactory.CreateScope())
{
var db=scope.ServiceProvider.GetService();
如果(asset.Device!=null)
{
db.Entry(asset.Device).State=EntityState.Modified;
}
asset.DateAdded=DateTime.UtcNow;
wait db.Assets.AddAsync(资产);
等待db.saveChangesSync();
归还资产;
}
}
catch(System.Exception-ex)
{
掷骰子;
}
}
}
AssetHub.cs-信号机集线器

 public class ChatHub : Hub
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly IServiceScopeFactory _serviceScopeFactory;

    public ChatHub(UserManager<ApplicationUser> userManager, IServiceScopeFactory serviceScopeFactory)
    {
        _userManager = userManager;
        _serviceScopeFactory = serviceScopeFactory;
    }

    public async Task SendAssetToGroup(string userName, string location, Asset asset)
    {

        if (!string.IsNullOrWhiteSpace(userName))
        {
            var user = await _userManager.Users.Include(x => x.Connections).SingleAsync(x => x.UserName == userName);

            if (user != null)
            {
                var group = $"{user.AccountId}-{location}";

                await Clients.Group(group).SendAsync("AssetUpdate", user.Email, asset);
            }
        }
    }

    public override async Task OnConnectedAsync()
    {
        var httpContext = Context.GetHttpContext();
        var location = httpContext.Request.Query["location"];

        using (var scope = _serviceScopeFactory.CreateScope())
        {
            var db = scope.ServiceProvider.GetService<ApplicationDbContext>();
            if (!string.IsNullOrWhiteSpace(userName))
            {

                var user = await db.Users.Include(x => x.Connections).SingleAsync(x => x.UserName == httpContext.User.Identity.Name);

                if (user != null)
                {
                    var group = $"{user.OrganizationId}-{location}";
                    var connection = new Connection { Connected = true, ConnectionId = Context.ConnectionId, Group = group, UserName = user.UserName };

                    await Groups.AddToGroupAsync(connection.ConnectionId, group);

                    user.Connections.Add(connection);

                    db.Users.Update(user);
                }
            }
           
            await db.SaveChangesAsync();
        }
        await base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(Exception exception)
    {
        if (!string.IsNullOrWhiteSpace(Context.ConnectionId))
        {
            using (var scope = _serviceScopeFactory.CreateScope())
            {
                var db = scope.ServiceProvider.GetService<ApplicationDbContext>();

                var connection = await db.Connections.Where(x => x.ConnectionId == 
                Context.ConnectionId).FirstOrDefaultAsync();

                if (connection != null)
                {
                    await Groups.RemoveFromGroupAsync(connection.ConnectionId, connection.Group);
                    db.Connections.Remove(connection);
                    await db.SaveChangesAsync();
                }
            }
        }

        await base.OnDisconnectedAsync(exception);
    }
}
公共类聊天中心:中心
{
私有只读用户管理器_UserManager;
专用readonly IServiceScopeFactory\u serviceScopeFactory;
公共聊天中心(UserManager UserManager、IServiceScopeFactory serviceScopeFactory)
{
_userManager=userManager;
_serviceScopeFactory=serviceScopeFactory;
}
公共异步任务SendAssetGroup(字符串用户名、字符串位置、资产)
{
如果(!string.IsNullOrWhiteSpace(用户名))
{
var user=await\u userManager.Users.Include(x=>x.Connections).SingleAsync(x=>x.UserName==UserName);
如果(用户!=null)
{
var group=$“{user.AccountId}-{location}”;
等待Clients.Group(Group.sendaync(“AssetUpdate”、user.Email、asset”);
}
}
}
公共覆盖异步任务OnConnectedAsync()
{
var httpContext=Context.GetHttpContext();
var location=httpContext.Request.Query[“location”];
使用(var scope=\u serviceScopeFactory.CreateScope())
{
var db=scope.ServiceProvider.GetService();
如果(!string.IsNullOrWhiteSpace(用户名))
{
var user=await db.Users.Include(x=>x.Connections).SingleAsync(x=>x.UserName==httpContext.user.Identity.Name);
如果(用户!=null)
{
var group=$“{user.OrganizationId}-{location}”;
var connection=新连接{Connected=true,ConnectionId=Context.ConnectionId,Group=Group,UserName=user.UserName};
wait Groups.AddToGroupAsync(connection.ConnectionId,group);
user.Connections.Add(连接);
db.Users.Update(用户);
}
}
等待db.saveChangesSync();
}
等待base.OnConnectedAsync();
}
公共覆盖异步任务OnDisconnectedAsync(异常)
{
如果(!string.IsNullOrWhiteSpace(Context.ConnectionId))
{
使用(var scope=\u serviceScopeFactory.CreateScope())
{
var db=scope.ServiceProvider.GetService();
var connection=await db.Connections.Where(x=>x.ConnectionId==
Context.ConnectionId).FirstOrDefaultAsync();
if(连接!=null)
{
wait Groups.RemoveFromGroupAsync(connection.ConnectionId,connection.Group);
db.连接。移除(连接);
等待db.saveChangesSync();
}
}
}
等待base.OnDisconnectedAsync(异常);
}
}
AssetTableChangeService.cs-这里是我需要帮助的地方。当SQLTableDependency检测到资产表的更改时,我需要能够调用AssetHB中的SendAssetToGroup方法。由于用户是组织的一部分,我不想将更新推送到所有组织,我只想将更新发送给特定组织组之外的用户

 public class AssetTableChangeService : IAssetTableChangeService
{
    private const string TableName = "Assets";
    private SqlTableDependency<Asset> _notifier;
    private IConfiguration _configuration;

    public event AssetChangeDelegate OnAssetChanged;

    public StockTableChangeService(IConfiguration configuration)
    {
        _configuration = configuration;

        // SqlTableDependency will trigger an event 
        // for any record change on monitored table  
        _notifier = new SqlTableDependency<Asset>(
             _configuration.GetConnectionString("DefaultConnection"),
             TableName);
        _notifier.OnChanged += AssetChanged;
        _notifier.Start();
    }

    private void AssetChanged(object sender, RecordChangedEventArgs<Asset> e)
    {

        OnAssetChanged.Invoke(this, new AssetChangeEventArgs(e.Entity, e.EntityOldValues));
    }

    public void Dispose()
    {
        _notifier.Stop();
        _notifier.Dispose();
    }
公共类AssetTableChangeService:IAssetTableChangeService
{
私有常量字符串TableName=“资产”;
私有SqlTableDependency\u通知程序;
专用IConfiguration\u配置;
已更改资产的公共事件资产更改委托;
public StockTableChangeService(IConfiguration配置)
{
_配置=配置;
//SqlTableDependency将触发一个事件
//对于监视表上的任何记录更改
_通知程序=新的SqlTableDependency(
_configuration.GetConnectionString(“DefaultConnection”),
表名);
_notifier.OnChanged+=AssetChanged;
_notifier.Start();
}
私有无效资产已更改(对象发送方,RecordChangedEventArgs e)
{
调用(这是新的AssetChangeEventArgs(e.Entity,e.EntityOldValues));
}
公共空间处置()
{
_notifier.Stop();
_Dispose();
}
所以流应该是这样的

  • 用户登录-通过信号器建立连接
  • 连接信息
     public class AssetTableChangeService : IAssetTableChangeService
    {
        private const string TableName = "Assets";
        private SqlTableDependency<Asset> _notifier;
        private IConfiguration _configuration;
    
        public event AssetChangeDelegate OnAssetChanged;
    
        public StockTableChangeService(IConfiguration configuration)
        {
            _configuration = configuration;
    
            // SqlTableDependency will trigger an event 
            // for any record change on monitored table  
            _notifier = new SqlTableDependency<Asset>(
                 _configuration.GetConnectionString("DefaultConnection"),
                 TableName);
            _notifier.OnChanged += AssetChanged;
            _notifier.Start();
        }
    
        private void AssetChanged(object sender, RecordChangedEventArgs<Asset> e)
        {
    
            OnAssetChanged.Invoke(this, new AssetChangeEventArgs(e.Entity, e.EntityOldValues));
        }
    
        public void Dispose()
        {
            _notifier.Stop();
            _notifier.Dispose();
        }