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.
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 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.
When you search the internet or SO how to connect to SQL database inside Script Task in SSIS you will find .NET v1.1ish code like this:
ConnectionManager cm;
System.Data.SqlClient.SqlConnection sqlConn;
System.Data.SqlClient.SqlCommand sqlComm;
cm = Dts.Connections["ADO.NET.SqlDB"];
sqlConn = (System.Data.SqlClient.SqlConnection)cm.AcquireConnection(Dts.Transaction);
sqlComm = new System.Data.SqlClient.SqlCommand("your SQL Command", sqlConn);
sqlComm.ExecuteNonQuery();
cm.ReleaseConnection(sqlConn);
I am looking for updated code that makes good use of later introduced .NET features.
For a start, how about the code below. Is this the current recommended way to connect to SQL Server inside Script Task in SSIS 2012 and later or do I miss something here?
ConnectionManager cm = Dts.Connections["ADO.NET.SqlDB"];
using (var sqlConn = (SqlConnection)cm.AcquireConnection(Dts.Transaction))
{
if (sqlConn.State != ConnectionState.Open)
sqlConn.Open();
using (var sqlComm = new SqlCommand(
String.Format("UPDATE myTab SET Processed = 4 where ID = '{0}'",
idNumber), sqlConn))
{
return sqlComm.ExecuteNonQuery();
}
}
Is the ReleaseConnection() still needed?
Is sqlConn.Open() really needed in an SSIS context?
One year later, and hopefully a little wiser, I settled with code like this:
ConnectionManager cm = Dts.Connections["ADO.NET.SqlServerDB"];
var sqlConn = (SqlConnection)cm.AcquireConnection(Dts.Transaction);
using (var sqlCmd = new SqlCommand(
"INSERT INTO apou_moodle_import(id_num, username, email) VALUES(#IdNum, #Username, #Email)",
sqlConn))
{
sqlCmd.CommandType = CommandType.Text;
sqlCmd.Parameters.AddWithValue("#IdNum", newUser.id_num);
sqlCmd.Parameters.AddWithValue("#Username", newUser.username);
sqlCmd.Parameters.AddWithValue("#Email", newUser.email);
int rowsAffected = sqlCmd.ExecuteNonQuery();
}
cm.ReleaseConnection(sqlConn);
So, I keep using ConnectionManager.ReleaseConnection, however, SqlConnection.Open & Close are not needed in an SSIS context. Plus, use Parameters to play safe.
Well, using structure allows you to automate disposing variables and handle it better. However, sqlConn is not a simple class, it is a ConnectionManager instance. When you start using it, you call AcquireConnection, when end - call ReleaseConnection. The ReleaseConnection may perform some housekeeping specific to this Data Source. Depending on ConnectionManager implementation, it may check at disposal whether ReleaseConnection was called or not and call it.
To my understanding, your code with using should be Ok in most cases. Problems may arise when you repeatedly open connections and do not release it - you might run of connection pool etc. I would wrap internals into try - finally block to ensure ReleaseConnection execution.
I want to use SQlLite Database in an ASP.NET Core project but without using an Entity Framework.
I think I should use a class which derives from DbProviderFactory & which caters to SQLLite database (something like System.Data.SqlClient.SqlClientFactory.Instance which is used for sqlServer) but I am unable to find it.
All the examples which i came across suggest me to use entity framework, but I don't want to use it.
You have it in official repo:
https://github.com/aspnet/Microsoft.Data.Sqlite
And here is an example:
http://www.bricelam.net/2015/04/29/sqlite-on-corefx.html
EDIT: adding link content in case it disappears in the future.
The provider is built on top of the System.Data.Common contract. This contract is a very small subset of the ADO.NET provider model. Using the provider should feel very natural to anyone familiar with ADO.NET.
using (var connection = new SqliteConnection("" +
new SqliteConnectionStringBuilder
{
DataSource = "hello.db"
}))
{
connection.Open();
using (var transaction = connection.BeginTransaction())
{
var insertCommand = connection.CreateCommand();
insertCommand.Transaction = transaction;
insertCommand.CommandText = "INSERT INTO message ( text ) VALUES ( $text )";
insertCommand.Parameters.AddWithValue("$text", "Hello, World!");
insertCommand.ExecuteNonQuery();
var selectCommand = connection.CreateCommand();
selectCommand.Transaction = transaction;
selectCommand.CommandText = "SELECT text FROM message";
using (var reader = selectCommand.ExecuteReader())
{
while (reader.Read())
{
var message = reader.GetString(0);
Console.WriteLine(message);
}
}
transaction.Commit();
}
}
Batching
The only real feature that the library adds to the native SQLite interfaces is batching. The native interfaces only support compiling and executing one statement at a time. This library implements batching in a way that should feel completely transparent. Here is an example of using batching.
using (var connection = new SqliteConnection("Data Source=hello.db"))
{
var command = connection.CreateCommand();
command.CommandText =
"UPDATE message SET text = $text1 WHERE id = 1;" +
"UPDATE message SET text = $text2 WHERE id = 2";
command.Parameters.AddWithValue("$text1", "Hello");
command.Parameters.AddWithValue("$text2", "World");
connection.Open();
command.ExecuteNonQuery();
}
Platforms:
Currently, Microsoft.Data.Sqlite works on the following platforms.
.NET Framework
Mono
.NET Core
.NET Native
CoreCLR
Windows Universal
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.