I use SignalR in my application and to react on database changes I've used Sql Dependency
SqlDependency.Start(con);
But I'm getting the following error:
Statement 'RECEIVE MSG' is not supported in this version of SQL Server
So as I understand Azure SQL Database doesn't support Service Broker.
Is there any solution, besides migrating to Azure VM?
Example of code with SQL Dependency:
public class NotificationComponent
{
public void RegisterNotification(DateTime currentTime)
{
string conStr = ConfigurationManager.ConnectionStrings["sqlConString"].ConnectionString;
string sqlCommand = #"SELECT [ContactID],[ContactName],[ContactNo] from [dbo].[Contacts] where [AddedOn] > #AddedOn";
using (SqlConnection con = new SqlConnection(conStr))
{
SqlCommand cmd = new SqlCommand(sqlCommand, con);
cmd.Parameters.AddWithValue("#AddedOn", currentTime);
if (con.State != System.Data.ConnectionState.Open)
{
con.Open();
}
cmd.Notification = null;
SqlDependency sqlDep = new SqlDependency(cmd);
sqlDep.OnChange += sqlDep_OnChange;
using (SqlDataReader reader = cmd.ExecuteReader())
{
}
}
}
void sqlDep_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
SqlDependency sqlDep = sender as SqlDependency;
sqlDep.OnChange -= sqlDep_OnChange;
var notificationHub = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
notificationHub.Clients.All.notify("added");
RegisterNotification(DateTime.Now);
}
}
public List<Contact> GetContacts(DateTime afterDate)
{
using (MyPushNotificationEntities dc = new MyPushNotificationEntities())
{
return dc.Contacts.Where(a => a.AddedOn > afterDate).OrderByDescending(a => a.AddedOn).ToList();
}
}
}
You can use the "when an item is created" and the "when an item is modified" triggers for SQL in Azure Logic App to react to data changes.
The SQL connector in Azure Logic Apps uses a polling mechanism to query a table for changes using a TIMESTAMP / ROWVERSION column. This data type is specifically designed for this kind of processing in SQL. The polling query essentially selects all rows where the rowversion is greater than the last polled value. The behavior is reliable since the column is controlled by SQL Server and the performance is extremely fast in the case where there is no new data. When there is new data, the performance is comparable to a simple row query.
For more information, please read this article.
Related
I am using extended events to log the query plan. I would also like to see the set options. How can I do this using extended events? (I know the profile shows the set options, but can this also be done using extended events?)
Background
I have a .NET core application that uses Entity Framework Core.
I connect to one database using a context and execute a LINQ query
And then within the first context I use SqlConnection + SqlCommand.ExecuteReader to execute a query directly on a 2nd database. The SqlCommand.ExecuteReader is slow (compared to direct execution in SQL Server Management Studio) and I would like to know what SET options are enabled.
Here is the pseudo code
using (var context = new MyDBContext(options))
{
var sensor = await context.Set<Sensor>()
.AsNoTracking()
.Where(s => s.Id == 4)
.SingleAsync(cancellationToken);
using (SqlConnection connection = new SqlConnection(connectionString2))
{
using (SqlCommand command = new SqlCommand(sql, connection))
{
connection.Open();
SqlDataReader reader = command.ExecuteReader();
try
{
reader.Read();
value = Convert.ToInt32(reader["CountColumn"]);
}
finally
{
reader.Close();
}
}
}
var newResult = new Result(sensor.Id, value);
context.Set<Result>().Add(newResult);
sensor.LatestResult = newResult;
context.Set<Sensor>().Update(sensor);
await context.SaveChangesAsync(cancellationToken);
}
i want call a C# method when i update table data or delete table data on every way like sql newquery 'Delete top(1) FROM [dbo].[Leaves]' like this and call c# method using store procedure. i perform it on sql dependencey but i don't need this i perform it using store procedure. you can see my code of sqldependecey. but i want another way to call this method using store procedure.
public class NotificationEvent
{
private delegate void RateChangeNotification(DataTable table);
private SqlDependency dependency;
string ConnectionString = #"Data Source=.;Initial Catalog=Message;Integrated Security=True";
string UserName = Environment.UserName;
public void RegisterForNotification()
{
var connectionString = ConnectionString;
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
var queryString = "SELECT [ID] FROM [dbo].[Leaves]";
using (var oCommand = new SqlCommand(queryString, connection))
{
// Starting the listener infrastructure...
SqlDependency.Start(connectionString);
var oDependency = new SqlDependency(oCommand);
oDependency.OnChange += OnNotificationChange;
// NOTE: You have to execute the command, or the notification will never fire.
oCommand.ExecuteReader();
}
}
}
private void OnNotificationChange(object sender, SqlNotificationEventArgs e)
{
Console.WriteLine("Notification Info: " + e.Info);
//Re-register the SqlDependency.
//var oDependency = new SqlDependency();
//oDependency.OnChange += OnNotificationChange;
RegisterForNotification();
}
}
#Umar Asif If the problem you face is totally regarding DB-to-DB communication, I would recommend a concept called "Merge Replication" in SQL Server (using Publisher-Subscriber(s)) design between DBs:
https://learn.microsoft.com/en-us/sql/relational-databases/replication/merge/merge-replication?view=sql-server-2017
Otherwise, if your problem requires a solution ONLY through a call to C# method, please refer:
How to call C# function in stored procedure
I am trying to implement SignalR in a.NET MVC5 application. I am using EF 6.0.0 and SignalR 2.2.3. I want to update the client screen whenever there's some change in the database (update,insert, delete). I've searched around and found a few articles that show how to setup SignalR to send real time messages like chat, then there are some articles that show how to do what I want to do but with ADO.NET instead of EF. Here's an article I found that uses ADO.NET to achive the same thing. What can I do to implement the same thing but with EF? Here's a code snippet from the article that handles the ADO.NET part of the process:
public class JobInfoRepository {
public IEnumerable<JobInfo> GetData()
{
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand(#"SELECT [JobID],[Name],[LastExecutionDate],[Status]
FROM [dbo].[JobInfo]", 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();
using (var reader = command.ExecuteReader())
return reader.Cast<IDataRecord>()
.Select(x => new JobInfo(){
JobID = x.GetInt32(0),
Name = x.GetString(1),
LastExecutionDate = x.GetDateTime(2),
Status = x.GetString(3) }).ToList();
}
}
}
I've also read the comments in the article and some people are saying dependency_OnChange method is firing continuously. Shouldn't it be fired only when we change something in a database? If it is supposed to fire continuously, we might as well use simple ajax polling and poll the db every second, right?
Is there another article explaining EF with SignalR that I can look into? Thanks
After some more research, I have found out that EF can not be used instead of ADO.NET when configuring the hub:
using (SqlCommand command = new SqlCommand(#"SELECT [JobID],[Name],[LastExecutionDate],[Status]
FROM [dbo].[JobInfo]", connection))
Since it uses SqlCommand and not any lamba expression.
when we work with sql dependency then we need to always refer a sql like below one SELECT ActivityDate FROM [bba-reman].MyLog
i just like to know if i write the above sql this way then does it work
SELECT TOP 1 ActivityDate FROM [bba-reman].MyLog OR
SELECT TOP 5 ActivityDate FROM [bba-reman].MyLog
i am looking for suggestion and guidance.
private void RegisterNotification()
{
string tmpdata = "";
System.Data.SqlClient.SqlDependency.Stop(connectionString);
System.Data.SqlClient.SqlDependency.Start(connectionString);
try
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT ActivityDate FROM [bba-reman].MyLog";
dep = new SqlDependency(cmd);
dep.OnChange += new OnChangeEventHandler(OnDataChange);
SqlDataReader dr = cmd.ExecuteReader();
{
while (dr.Read())
{
if (dr[0] != DBNull.Value)
{
tmpdata = dr[0].ToString();
}
}
}
dr.Dispose();
cmd.Dispose();
}
}
finally
{
//SqlDependency.Stop(connStr);
}
}
According to the SQL Server Books Online (https://msdn.microsoft.com/en-us/library/t9x04ed2.aspx), one of the restrictions for using QueryNotifications is that the statement must not use a TOP expression. SqlDependency is just a higher level implementation of QueryNotifications that takes care of the Service Broker plumbing.
The SqlDependency class has a lot of restrictions as well as the memory leak problems. An absence of the TOP instruction is the one of them. Hovewer, you can use an open source realization of the SqlDependency class - SqlDependencyEx. It uses a database trigger and native Service Broker notification to receive events about the table changes. This is an usage example:
int changesReceived = 0;
using (SqlDependencyEx sqlDependency = new SqlDependencyEx(
TEST_CONNECTION_STRING, TEST_DATABASE_NAME, TEST_TABLE_NAME))
{
sqlDependency.TableChanged += (o, e) => changesReceived++;
sqlDependency.Start();
// Make table changes.
MakeTableInsertDeleteChanges(changesCount);
// Wait a little bit to receive all changes.
Thread.Sleep(1000);
}
Assert.AreEqual(changesCount, changesReceived);
With SqlDependecyEx you are able to monitor INSERT, DELETE, UPDATE separately and receive actual changed data (xml) in the event args object. Filtering incoming messages helps you implement desirable behavior. Hope this help.
I have a console application.
I wanna keep watching the changes on a specific column in my database table.
I read through internet and I have found that sql dependency is good for my purpose. I started learning about it and I did the following:
create a class.
In the constructor, I called the static function start and I called a function that has all the sql dependency settings.
My problem
When I run the application using the start click on visual studio 2013, the apps works and then stops. However, what I need is that the apps starts working and keep watching for changes in my database's table.
Could you help me please?
Code:
This is a very very simple c# code.
public class MyListener
{
public MyListener()
{
SqlDependency.Start(getConnectionString());
this.listen();
}
private string getConnectionString()
{
return ConfigurationManager.ConnectionStrings["popup"].ConnectionString.ToString();
}
private void listen()
{
string query = "SELECT CallerID FROM TransferToSIP WHERE hasBeenRead = 0";
SqlConnection con = new SqlConnection(getConnectionString());
SqlCommand cmd = new SqlCommand(query, con);
con.Open();
using (cmd)
{
SqlDependency dependency = new SqlDependency(cmd);
dependency.OnChange += new
OnChangeEventHandler(OnDependencyChange);
using (SqlDataReader reader = cmd.ExecuteReader())
{
}
}
}
void OnDependencyChange(object sender, SqlNotificationEventArgs e)
{
Console.WriteLine("Roma");
}
void Termination()
{
SqlDependency.Stop(getConnectionString());
Console.Read();
}
The problem is in absence of the resubscruption. You should call the listen method inside of OnDependencyChange. I know that it is weird, but it is the SqlDependency class.
Be careful using the SqlDependency class to monitor changes in the database tables - it has the problems with the memory leaks. However, you can use your own realization with DDL triggers and SQL Service Broker API or use one of an open source projects, e.g. SqlDependencyEx:
int changesReceived = 0;
using (SqlDependencyEx sqlDependency = new SqlDependencyEx(
TEST_CONNECTION_STRING, TEST_DATABASE_NAME, TEST_TABLE_NAME))
{
sqlDependency.TableChanged += (o, e) => changesReceived++;
sqlDependency.Start();
// Make table changes.
MakeTableInsertDeleteChanges(changesCount);
// Wait a little bit to receive all changes.
Thread.Sleep(1000);
}
Assert.AreEqual(changesCount, changesReceived);
Hope this helps.