SignalR(v2.2.0)OnDisconnected设置用户离线

我使用以下代码在组中添加用户并使用以下代码将用户保存在db中。

服务器:

public class ChatHub : Hub { public async Task JoinRoom(string user_Id, string room_Id, string user_Name) { AddLoginUser(room_Id, this.Context.ConnectionId, user_Id); await this.Groups.Add(this.Context.ConnectionId, room_Id); } public void Connect(string user_Id, string room_Id, string user_Name) { var id = Context.ConnectionId; Clients.Caller.onConnected(id, user_Name, GetRoomUser(room_Id), GetRoomMessage(room_Id)); // send to all in group to update user list Clients.OthersInGroup(room_Id).onNewUserConnected(id, user_Name); } public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled) { using (DataContext dc = new DataContext()) { var item = dc.LoggedInUsers.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId); if (item != null) { item.Connected = false; dc.SubmitChanges(); Clients.OthersInGroup(item.RoomID.ToString()).onUserDisconnected(Context.ConnectionId, item.UserMaster.User_Name); } return base.OnDisconnected(stopCalled); } } } private void AddLoginUser(string room_Id, string connection_Id, string user_Id) { using (DataContext dc = new DataContext()) { var checkUserLogedIn = (from user in dc.LoggedInUsers where (user.RoomID == Convert.ToInt32(room_Id) && user.UserID == Convert.ToInt32(user_Id)) select user).SingleOrDefault(); if (checkUserLogedIn == null) { LoggedInUser objLoggedInUser = new LoggedInUser(); objLoggedInUser.ConnectionId = connection_Id; objLoggedInUser.UserID = Convert.ToInt32(user_Id); objLoggedInUser.RoomID = Convert.ToInt32(room_Id); objLoggedInUser.Connected = true; dc.LoggedInUsers.InsertOnSubmit(objLoggedInUser); dc.SubmitChanges(); } else { if (!checkUserLogedIn.Connected) { checkUserLogedIn.Connected = true; dc.SubmitChanges(); } } } } 

问题:

假设我使用userid = 1登录roomid = 1和contextid = 123asd。 如果我刷新我的窗口,那么contextid将会改变,现在如果我关闭浏览器选项卡然后跟随查询:

 var item = dc.LoggedInUsers.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId); 

没有找到针对最新connectionid的用户,因为当我在连接时保存用户时,connectionid是不同的。

如何在断开事件时为特定用户设置连接状态为false。

提前致谢。

OnConnected您应该保存所有connectionIds(与用户映射),connectionId应该是唯一的,而不是用户。 因为用户可以同时与信号器建立多个连接(新标签)。

每次你应该在Onconnected上映射user和connectionId。 每次你应该删除那个connectionId,而不是OnDisconnected上的所有OnDisconnected用户。 如果它不在列表中,则应该将connectionId添加到用户(如果在OnReconnected上,即使用户未断开连接,也不会调用停止调用断开连接)。

你应该重构你的代码库。 首先,您应该删除connectionId。 然后,你可以检查; 如果列表中没有该用户(使用该connectionId映射)的记录,则可以发送消息。

点击这里

我已经更改了一些代码,您可以根据这些知识改进此代码。 您还应该在AddLoginUser上调用AddLoginUser

  public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled) { using (DataContext dc = new DataContext()) { var item = dc.LoggedInUsers.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId); if (item != null) { dc.LoggedInUsers.Remove(item); dc.SubmitChanges(); //If there is no other connection left with this user in this room send message. if (!dc.LoggedInUsers.Any(x => x.RoomID==item.RoomID && x.userId==item.UserId) Clients.OthersInGrouproomId.ToString()).onUserDisconnected(Context.ConnectionId, item.UserMaster.User_Name); } return base.OnDisconnected(stopCalled); } } } private void AddLoginUser(string room_Id, string connection_Id, string user_Id) { using (DataContext dc = new DataContext()) { //Just check connectionId uniqunes. You don't need connected field. var checkUserLogedIn = (from user in dc.LoggedInUsers where user.ConnectionId == connection_Id select user).SingleOrDefault(); if (checkUserLogedIn == null) { LoggedInUser objLoggedInUser = new LoggedInUser(); objLoggedInUser.ConnectionId = connection_Id; objLoggedInUser.UserID = Convert.ToInt32(user_Id); objLoggedInUser.RoomID = Convert.ToInt32(room_Id); dc.LoggedInUsers.InsertOnSubmit(objLoggedInUser); dc.SubmitChanges(); } } } 
Interesting Posts