I have the following code which displays live data using SignalR. The table gets updated instantly using SignalR once a row is inserted, updated, or deleted. However, I would like to know in particular the type of change that happened to the database (whether it's an update, delete, or insert). I understand that the onchange() method detects changes on the database, but how can I determine what type of change it is?
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionCustomer"].ConnectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand(#"SELECT [Id],[CustomerName] FROM [CustomerInfoes] ", connection))
{
// Make sure the command object does not already have
// a notification object associated with it.
command.Notification = null;
SqlDependency dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
if (connection.State == ConnectionState.Closed)
connection.Open();
SqlDataReader reader = command.ExecuteReader();
var listCus = reader.Cast<IDataRecord>()
.Select(x => new
{
Id = (int)x["Id"],
CustomerName = (string)x["CustomerName"],
}).ToList();
return Json(new { listCus = listCus }, JsonRequestBehavior.AllowGet);
}
}
}
private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
CustomerHub.Show();
}
Hub:
public static void Show()
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<CustomerHub>();
context.Clients.All.displayCustomer();
}
View
<script src="~/signalr/hubs" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
// Proxy created on the fly
var cus = $.connection.customerHub;
// Declare a function on the job hub so the server can invoke it
cus.client.displayCustomer = function () {
getData();
};
// Start the connection
$.connection.hub.start();
getData();
});
function getData() {
var $tbl = $('#tblInfo');
$.ajax({
url: $("#Get").val(),
type: 'GET',
datatype: 'json',
success: function (data) {
$tbl.empty();
$.each(data.listCus, function (i, model) {
$tbl.append
(
'<tr>' +
'<td>' + model.Id + '</td>' +
'<td>' + model.CustomerName + '</td>' +
'<tr>'
);
});
}
});
}</script>
You can easily find out the change type by looking at eventArgs.Info property.
finally I know how to call the method in the server and the client will refresh the chart. if you update data on table, the chart will adjust automatically. the code as below:
this is my html code:
<div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<script src="Scripts/jquery.signalR-2.2.1.min.js"></script>
<script src="../signalR/hubs"></script>
<script type="text/javascript">
$(function () {
//proxy created on the fly
var job = $.connection.statisticsHub;
//declare a function on the job hub so the server can invoke it
job.client.displayStatus = function () {
getData();
};
//start the connection
$.connection.hub.start()
.done(function () {
console.log('now connected');
//execute function in client from server
job.server.show();
})
.fail(function (error) {
console.log('error nih: ' + error);
});
});
function getData() {
//alert("from getData");
google.load("visualization", "1", { packages: ["corechart"] });
google.setOnLoadCallback(drawChart);
function drawChart() {
var options = {
title: 'USA City Distribution'
};
$.ajax({
type: "POST",
url: "Default.aspx/GetChartData",
data: '{}',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (r) {
var data = google.visualization.arrayToDataTable(r.d);
var chart = new google.visualization.PieChart($("#chart")[0]);
chart.draw(data, options);
},
failure: function (r) {
alert(r.d);
},
error: function (r) {
alert(r.d);
}
});
}
}
</script>
<div id="chart" style="width: 900px; height: 500px;">
</div>
this is Hub:
using Microsoft.AspNet.SignalR;
namespace TutorialGooglePieChart
{
public class StatisticsHub : Hub
{
public void Show()
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<StatisticsHub>();
context.Clients.All.displayStatus();
}
}
}
this is my cs file:
using System;
using System.Collections.Generic;
using System.Data;
using System.Web.Services;
using System.Configuration;
using System.Data.SqlClient;
namespace TutorialGooglePieChart
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
[WebMethod]
public static List<object> GetChartData()
{
string query = "SELECT Name, Quantity FROM [dbo].[Products]";
string constr = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
List<object> chartData = new List<object>();
chartData.Add(new object[]
{
"Name", "Quantity"
});
using (SqlConnection con = new SqlConnection(constr))
{
using (SqlCommand cmd = new SqlCommand(query))
{
cmd.CommandType = CommandType.Text;
cmd.Connection = con;
cmd.Notification = null;
SqlDependency.Start(ConfigurationManager.ConnectionStrings["constr"].ConnectionString);
SqlDependency dependency = new SqlDependency(cmd);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
con.Open();
using (SqlDataReader sdr = cmd.ExecuteReader())
{
while (sdr.Read())
{
chartData.Add(new object[]
{
sdr["Name"], sdr["Quantity"]
});
}
}
con.Close();
return chartData;
}
}
}
private static void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
StatisticsHub myHub = new StatisticsHub();
myHub.Show();
}
}
}
}
thank you for your help
Without testing it, the java script looks okay.
Your method needs to be updated, remove static from your method, not positive but I think that is where your main problem is. Comment out the IHubContext as I don't believe it is needed since you are within the hub. I think that is for calling methods (in your hub) from other classes.
Also, changing Clients.All to Clients.Caller. It would not make sense to update everyone's chart when anyone connects. Rather only the calling client.
Try changing to this:
using Microsoft.AspNet.SignalR;
namespace TutorialGooglePieChart
{
public class StatisticsHub : Hub
{
public void Show()
{
//IHubContext context = GlobalHost.ConnectionManager.GetHubContext<StatisticsHub>();
//context.Clients.All.displayStatus();
context.Clients.Caller.displayStatus();
}
}
}
I am trying to visualize data using google charts.But the chart is not displaying.I want to display data which is retrieved from sqlserver database
here is my code.
<div id="chart_div" style="width:500px;height:400px">
<%-- Here Chart Will Load --%>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['bar']});
google.charts.setOnLoadCallback(drawStuff);
function drawStuff() {
var jdata = $.ajax({
url: "GetData.aspx",
dataType: "json",
async: false
}).responseText;
var data = new google.visualization.DataTable(jData);
var options = {
title: 'Chess opening moves',
width: 900,
legend: { position: 'none' },
chart: {
title: 'Chess opening moves',
subtitle: 'popularity by percentage'
},
bars: 'horizontal', // Required for Material Bar Charts.
axes: {
x: {
0: { side: 'top', label: 'amount' } // Top x-axis.
}
},
bar: { groupWidth: "90%" }
};
var chart = new google.charts.Bar(document.getElementById('chart_div'));
chart.draw(data, options);
};
</script>
</div>
GetData.aspx
public partial class GetData : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
JavaScriptSerializer js = new JavaScriptSerializer();
string arr = JsonConvert.SerializeObject(get(), Formatting.None,
new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
Response.Write(arr);
}
private object get()
{
List<object> ls = new List<object>();
SqlConnection con = new SqlConnection("Data Source=dell-pc;Initial Catalog=hospital;Integrated Security=True");
SqlCommand cmd = new SqlCommand("select top(5) p_id, amount from payments", con);
con.Open();
DataTable dt = new DataTable();
SqlDataAdapter adp = new SqlDataAdapter(cmd);
adp.Fill(dt);
foreach (DataRow dr in dt.Rows)
{
ls.Add(dr);
}
return ls;
}
}
The JsonArray loads as follows.
[{"RowError":"","RowState":2,"Table":[{"p_id":"PT1","amount":7000.0000},{"p_id":"PT2","amount":35000.0000},{"p_id":"PT8","amount":95000.0000},{"p_id":"PT10","amount":51000.0000},{"p_id":"PT3","amount":1200.0000}],"ItemArray":["PT1",7000.0000],"HasErrors":false},{"RowError":"","RowState":2,"Table":[{"p_id":"PT1","amount":7000.0000},{"p_id":"PT2","amount":35000.0000},{"p_id":"PT8","amount":95000.0000},{"p_id":"PT10","amount":51000.0000},{"p_id":"PT3","amount":1200.0000}],"ItemArray":["PT2",35000.0000],"HasErrors":false},{"RowError":"","RowState":2,"Table":[{"p_id":"PT1","amount":7000.0000},{"p_id":"PT2","amount":35000.0000},{"p_id":"PT8","amount":95000.0000},{"p_id":"PT10","amount":51000.0000},{"p_id":"PT3","amount":1200.0000}],"ItemArray":["PT8",95000.0000],"HasErrors":false},{"RowError":"","RowState":2,"Table":[{"p_id":"PT1","amount":7000.0000},{"p_id":"PT2","amount":35000.0000},{"p_id":"PT8","amount":95000.0000},{"p_id":"PT10","amount":51000.0000},{"p_id":"PT3","amount":1200.0000}],"ItemArray":["PT10",51000.0000],"HasErrors":false},{"RowError":"","RowState":2,"Table":[{"p_id":"PT1","amount":7000.0000},{"p_id":"PT2","amount":35000.0000},{"p_id":"PT8","amount":95000.0000},{"p_id":"PT10","amount":51000.0000},{"p_id":"PT3","amount":1200.0000}],"ItemArray":["PT3",1200.0000],"HasErrors":false}]
I think there is something wrong when json is loading. please help
The main reason here that you fail to load json data is probably because you use a full aspx page GetData.aspx (and there you send wrong header, content type)
Change that to a handler, make a new handler not just rename the page, something like getdata.ashx and place there your code.
Be sure to send the correct content type context.Response.ContentType, and check that you send only the correct json data
the answers here can help : ASP.NET Returning JSON with ASHX
I need SQL Dependency change on a gridview displaying all rows that are changed or old data. Can anybody help me?
Here is my script:
<script>
$(function () {
var notify = $.connection.notificationsHub;
notify.client.displayNotification = function (msg) {
$("#newData").html(msg);
};
$.connection.hub.start();
});
</script> </head> <body>
<form id="form1" runat="server">
<div>
<asp:GridView id="newData" runat="server" AutoGenerateColumns="False">
</asp:GridView>
public void SendNotifications()
{
string message = string.Empty;
string conStr = ConfigurationManager.ConnectionStrings["TestDB"].ConnectionString;
using (SqlConnection connection = new SqlConnection(conStr))
{
string query = "SELECT [Message] FROM [dbo].[tb]";
using (SqlCommand command = new SqlCommand(query, connection))
{
command.Notification = null;
SqlDependency dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
message = reader.GetString(0);
}
}
}
}
NotificationsHub nHub = new NotificationsHub();
nHub.NotifyAllClients(message);
}
private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
SendNotifications();
}
}
i followed the tutorial to from one of the online blog and am able get the application out with out error, but main issue is its not giving error as well as output.
My hub class looks like this
public void NotifyAllClients(string msg)
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<NotificationsHub>();
context.Clients.All.displayNotification(msg);
}
My ASPX.CS page looks like this
protected void Page_Load(object sender, EventArgs e)
{
SendNotifications();
}
public void SendNotifications()
{
string message = string.Empty;
string conStr = ConfigurationManager.ConnectionStrings["TestDB"].ConnectionString;
using (SqlConnection connection = new SqlConnection(conStr))
{
string query = "SELECT [Message] FROM [dbo].[MessageBuffer]";
using (SqlCommand command = new SqlCommand(query, connection))
{
command.Notification = null;
SqlDependency dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
message = reader[0].ToString();
}
}
}
NotificationsHub nHub = new NotificationsHub();
nHub.NotifyAllClients(message);
}
private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
SendNotifications();
}
}
and My aspx page is --
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<script src="Scripts/jquery-1.8.2.min.js"></script>
<script src="Scripts/jquery.signalR-2.1.2.js"></script>
<script src="signalr/hubs"></script>
<script type="text/javascript">
$(function () {
var notify = $.connection.notificationsHub;
notify.client.displayNotification = function (msg) {
$('#newData').append('<li><strong>' + msg + '</li>');
};
$.connection.hub.start();
});
</script>
<div style="padding:10px 0px 10px 10px">
New Messages:
<ul id="newData"></ul>
</div>
</body>
</html>
i have done different samples, i have used same format to display, i am able to get those out in a hand, but here i am stuck with this. i am getting value in aspx.cs page, it calling the DB, which i have given in global.asax. and i have added sqldependency as well, enbabled broker in DB. but issue is still there. i cant see anything in UI.
Thanks in advance
I had a similar problem a while back. I just used the hub method name attribute and it worked for me. So you want something like
[HubMethodName("SendNotifications")]
public string SendNotifications()
And then at the front end just do
$.connection.hub.start(function () {
notify.server.SendNotifications();
});
Update
You could have a span the way I have in my code. so something like
<div>
<ul>
<li>New Messages:<span id="newData">0</span></a></li>
</ul>
</div>
Then do
$('#newData').text(msg);