问题
I am using SignalR and SQL dependency to deliver real time data based on a SQL Server query with parameter related to the user connectionId.
I have a strange problem related to SQL depedency: I am sending a userid through query string to the hub.
For each hub start, I am saving the connection Id and that userId in SQL Server database and my SQL query which I am linking to SQL dependency has filter related to the connectionId.
I tried to include the filter based on that connectionId in the query itself, but SQL dependency was not updating: the data are displayed only on starting, and if I update them in the database, they are not updated in the client
If I hard code the connection id value, SQL dependency works fine
Then I tried another solution: I don't put the filter in the original query, but I filter the result using LinQ => SQL dependency does not work (same result as in 1)
Another filtration way: using DataView => same result as in 1 and 3
My hub:
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Threading.Tasks;
using MapUsers;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using System.Data.Entity;
using SignalRDbUpdates.Models;
namespace SignalRDbUpdates.Hubs
{
[HubName("agendaHub")]
public class AgendaHub : Hub
{
string Mat = "";
Int16 nb_formation = 0;
Int16 nb_audit=0;
Int16 nb_action=0;
Int16 nb_reunion=0;
Int16 nb_equipement = 0;
string ConnectionId = "";
string ConId = "";
public static List<UserConnection> ListUser { get; set; }
public class UserConnection
{
public string UserId { get; set; }
public string ConnectionId { get; set; }
}
public void Hello()
{
Clients.All.hello();
}
public override Task OnConnected()
{
//var name = Context.User.Identity.Name;
try
{
ConId = Context.ConnectionId;
string mat;
mat = "";
try
{
mat = Context.QueryString["uid"].ToString();
}
catch (Exception e)
{
Cldb.Insert_error(e.Message.ToString() + " " + e.InnerException.ToString(), e.StackTrace.ToString(), "onConnected, QueryString");
}
ListUser = new List<UserConnection>();
var us = new UserConnection
{
UserId = Context.QueryString["uid"].ToString(),
ConnectionId = Context.ConnectionId
};
ListUser.Add(us);
Cldb.Add_connection_to_agenda_table(mat, Context.ConnectionId);
using (var db = new UserContext())
{
var user = db.Users
.Include(u => u.Connections)
.SingleOrDefault(u => u.UserName == mat);
if (user == null)
{
user = new User
{
UserName = mat,
Connections = new List<Connection>()
};
db.Users.Add(user);
}
user.Connections.Add(new Connection
{
ConnectionID = Context.ConnectionId,
UserAgent = Context.Request.Headers["User-Agent"],
Connected = true,
ConnectionTime = DateTime.Now
});
db.SaveChanges();
}
}
catch (Exception e)
{
Cldb.Insert_error(e.Message.ToString() + " " + e.InnerException.ToString(), e.StackTrace.ToString(), "onConnected");
}
return base.OnConnected();
}
public override Task OnDisconnected(bool stopCalled)
{
try
{
Cldb.Remove_connection_from_agenda_table(Context.ConnectionId);
using (var db = new UserContext())
{
var connection = db.Connections.Find(Context.ConnectionId);
connection.Connected = false;
connection.DeConnectionTime = DateTime.Now;
db.SaveChanges();
}
}
catch (Exception e)
{
Cldb.Insert_error(e.Message.ToString() + " " + e.InnerException.ToString(), e.StackTrace.ToString(), "OnDisconnected");
}
return base.OnDisconnected(stopCalled);
}
[HubMethodName("updateAgenda")]
public string UpdateAgenda()
{
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["QualiproConnection"].ConnectionString))
{
connection.Open();
/*string query = "select [mat],[nb_formation] " +
",[nb_audit],[nb_action],[nb_reunion],[nb_equipement] from dbo.[tab_agenda] where [mat]="+ Mat;
/*"[nb_fournisseur],[nb_reclamation],[nb_document],[nb_indicateur],[nb_non_conformite]," +
"[nb_environnement],[nb_haccp1],[nb_haccp2]," +
"[nb_coq],[nb_verif],[nb_courrier],[nb_habilitation]," +
"[nb_amdec],[nb_secur],[nb_conf_reg],[nb_part_int],[nb_risque]," +
"[nb_achat],[nb_doc_group],[nb_reunion_info]," +
"[nb_action_uni],[nb_changement] from dbo.[tab_agenda] ";*/
using (
//Solution 1 and 2 : Filter in the Original Query
//var command = new SqlCommand(@"select [mat],[nb_formation] ,[nb_audit],[nb_action],[nb_reunion],[nb_equipement] from dbo.[tab_agenda] where [ConnectionId]=@conId" , connection))
//Solution 2, : No Filter in the original Query
var command = new SqlCommand("select [connectionId],[mat],[nb_formation] ,[nb_audit],[nb_action],[nb_reunion],[nb_equipement] from dbo.[tab_agenda]", connection))
{
// This is Not used any more, not working
// command.Parameters.AddWithValue("@mat", Cldb.Get_client_mat(Context.ConnectionId));
// Solution 2: Filter parameter is hard coded => SQL DEPENDENCY WORKS
//command.Parameters.AddWithValue("@conId", "c6103452-8886-44d9-8ff2-5463884243c2");
//Solution 3 : Filter parameter coming from connectionId ==> data are displayed on start but then sql dependency is not updating the data
////command.Parameters.AddWithValue("@conId", Context.ConnectionId);
/*string Id = ListUser.Find(x => x.ConnectionId == Context.ConnectionId).UserId;*/
//command.Parameters.AddWithValue("@conId", ConId);
command.Notification = null;
DataTable dt = new DataTable();
SqlDependency dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(Dependency_OnChange);
if (connection.State == ConnectionState.Closed)
connection.Open();
var reader = command.ExecuteReader();
dt.Load(reader);
if (dt.Rows.Count > 0)
{
//Solution 3 : FILTERING the data using LINQ => SQL dependency is not working
//var dataRow = dt.AsEnumerable().Where(x => x.Field<string>("connectionId") == Context.ConnectionId).FirstOrDefault();
//Solution 4 : Filtering data using Dataview filer => SQL dependency is not working
/*DataView dv = new DataView(dt)
{
RowFilter = "connectionId='" + Context.ConnectionId + "'"
};*/
//if (dv.Count > 0)
//if (dataRow != null)
{
//dt = dv.ToTable();
Mat = dt.Rows[0]["Mat"].ToString();
ConnectionId = dt.Rows[0]["ConnectionId"].ToString();
nb_formation = Int16.Parse(dt.Rows[0]["nb_formation"].ToString());
nb_audit = Int16.Parse(dt.Rows[0]["nb_audit"].ToString());
nb_action = Int16.Parse(dt.Rows[0]["nb_action"].ToString());
nb_equipement = Int16.Parse(dt.Rows[0]["nb_equipement"].ToString());
nb_reunion = Int16.Parse(dt.Rows[0]["nb_reunion"].ToString());
/*Mat = dataRow["Mat"].ToString();
ConnectionId = dataRow["ConnectionId"].ToString();
nb_formation = Int16.Parse(dataRow["nb_formation"].ToString());
nb_audit = Int16.Parse(dataRow["nb_audit"].ToString());
nb_action = Int16.Parse(dataRow["nb_action"].ToString());
nb_equipement = Int16.Parse(dataRow["nb_equipement"].ToString());
nb_reunion = Int16.Parse(dataRow["nb_reunion"].ToString());*/
}
}
}
}
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<AgendaHub>();
return context.Clients.All.recieveagenda(Mat, ConnectionId,nb_formation, nb_audit,nb_action,nb_equipement,nb_reunion);
}
private void Dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
AgendaHub nHub = new AgendaHub();
nHub.UpdateAgenda();
}
}
}
}
The client:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>SignalR SQL Server dependancy Client</title>
<style type="text/css">
.auto-style1 {
width: 166px;
}
</style>
</head>
<script src='http://localhost:210/scripts/jquery-1.10.2.min.js' type="text/javascript"></script>
<script type="text/javascript">
$.getScript('http://localhost:210/Scripts/jquery.signalR-2.1.1.min.js', function () {
$.getScript('http://localhost:210/signalr/hubs', function () {
// Declare a proxy to reference the hub.
$.connection.hub.url = 'http://localhost:210/signalr';
var notifications = $.connection.agendaHub;
$.connection.hub.qs = { 'uid': '100' };
// Create a function that the hub can call to broadcast messages.
notifications.client.recieveagenda = function (Mat, ConnectionId,nb_formation,nb_audit,nb_action,nb_equipement,nb_reunion)
{
// Add the message to the page.
$('#spanconId').text($.connection.hub.id);
$('#span_conId').text(ConnectionId);
$('#spanMat').text(Mat);
$('#spannb_Formation').text(nb_formation);
$('#spannb_Audit').text(nb_audit);
$('#spannb_Reunion').text(nb_reunion);
$('#spannb_Equipement').text(nb_equipement);
$('#spannb_Action').text(nb_action);
};
// Start the connection.
$.connection.hub.start().done(function () {
alert("connection started");
notifications.server.updateAgenda();
}).fail(function (e) {
alert(e);
});
$.connection.hub.disconnected(function () { $.connection.hub.start();});
//$.connection.hub.start();
});
});
</script>
<body>
<form id="form1" runat="server">
<h1>Notifications</h1>
<div>
<table>
<tr>
<td><span id="spanconId"></span></td>
</tr>
</table>
<table border="1" style="width: 510px">
<tr>
<td class="auto-style1">ConnectionId</td>
<td><span id="span_conId"></span></td>
</tr>
<tr>
<td class="auto-style1">Mat</td>
<td><span id="spanMat"></span></td>
</tr>
<tr>
<td class="auto-style1">nb Formation</td>
<td><span id="spannb_Formation"></span></td>
</tr>
<tr>
<td class="auto-style1">nb Audit</td>
<td><span id="spannb_Audit"></span></td>
</tr>
<tr>
<td class="auto-style1">nb Action</td>
<td><span id="spannb_Action"></span></td>
</tr>
<tr>
<td class="auto-style1">nb Réunion</td>
<td><span id="spannb_Reunion"></span></td>
</tr>
<tr>
<td class="auto-style1">nb Equipement</td>
<td><span id="spannb_Equipement"></span></td>
</tr>
</table>
</div>
</form>
</body>
</html>
来源:https://stackoverflow.com/questions/59325162/filtering-data-table-inside-hub-class-prevents-sql-dependency-to-run