I am building a web application where a job submitted by user is handled by a background service and the communication between web app and background service is done on database. So when a search starts, web application inserts a record into db and waits till the status field of the record changes. As I understand, if I implement this on the request thread, I am blocking one of the pool threads unnecessarily, but cannot get my head around to do this asynchronously. What is the best practice in this case?
SQLDependency is very useful, but on the server side it provided only half the solution. I overcame the other half by using SignalR to signal the client that the query is over. In the end it was quite an efficient and elegant solution. Thanks for the info!
public class KYHub : Hub
{
void OnChange(object sender, SqlNotificationEventArgs e)
{
SqlDependency dependency = sender as SqlDependency;
dependency.OnChange -= OnChange;
if (e.Info != SqlNotificationInfo.Error && e.Info != SqlNotificationInfo.Delete)
{
string connstr = System.Configuration.ConfigurationManager.ConnectionStrings["cnnStr"].ConnectionString;
SqlConnection conn = new SqlConnection(connstr);
conn.Open();
SearchResult result= SearchResult.Parse(conn, Caller.TaskID);
conn.Close();
Caller.endsearch(result);
}
}
public void Search(SearchParam search)
{
string connstr = System.Configuration.ConfigurationManager.ConnectionStrings["cnnStr"].ConnectionString;
SqlConnection conn = new SqlConnection(connstr);
conn.Open();
search.ClientID = Caller.id;
int QueryID = search.Save(conn);
Caller.TaskID = QueryID;
SqlCommand cmd = new SqlCommand(String.Format("SELECT Completed FROM dbo.Tasks WHERE TaskID={0}", QueryID), conn);
SqlDependency dep = new SqlDependency(cmd);
dep.OnChange += OnChange;
cmd.ExecuteReader();
conn.Close();
}
}
If you are using SQL Server as your DB then you can use a ADO.NET feature called SQLDependency,
What this dose when setup correctly is, when ever there is a change in table (which you will configure) a C# event will be raised.
Here is a article that expains it
Note: You will have to setup your SQL server to enable this.
http://www.codeproject.com/Articles/12335/Using-SqlDependency-for-data-change-events
And this one expains how to refresh page after data in table has changed
http://msdn.microsoft.com/en-us/library/e3w8402y%28v=vs.80%29.aspx
Related
i through i will call SQL Dependency related code Application_Start event and my objective will be completed. my scenario is i have a routine in my web application which i invoke manually just clicking on a button when data updated in sql server table. i was told to make this process automated.
so i go through couple of article on SQL Dependency and through i can make my manual process automated by SQL Dependency because we can monitor table change by SQL Dependency and SQL Dependency can notify us when change done.
please see my code
protected void Application_Start(Object sender, EventArgs e)
{
System.Data.SqlClient.SqlDependency.Stop(connectionString);
System.Data.SqlClient.SqlDependency.Start(connectionString);
RegisterNotification();
}
static SqlDependency dep;
private static void RegisterNotification()
{
string tmpdata = "";
try
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT ActivityDate FROM [bba-reman].ContentChangeLog";
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);
}
}
static void OnDataChange(object sender, SqlNotificationEventArgs e)
{
SqlDependency dep = sender as SqlDependency;
dep.OnChange -= new OnChangeEventHandler(OnDataChange);
SiteSearch.CreateIndex(false);
RegisterNotification();
}
protected void Application_End(Object sender, EventArgs e)
{
System.Data.SqlClient.SqlDependency.Stop(connectionString);
}
the above code was running fine but i faced a good problem. suppose no visitor is visiting our web site and at the same time if some one change sql data by a win apps then i saw OnDataChange() event is not firing but if at least one visitor is with our site then OnDataChange() event is firing properly.
may be this is default nature of asp.net engine. i could use SQL Dependency in win service or in winform apps but i have some constrain because the routine which i am calling after detection of data change in db that is in our web application.
So please guide me what i can do as a result OnDataChange() event should always fire if no visitor is visiting our web site.
thanks
I'm a complete beginner in ASP.Net webservices can anyone point me to a good tutorial by which I may implement a web service with SQL Server database connectivity?
Thanks in advance
1. Create the Project in Visual Studio
go to Visual Studio>New Project(select .Net Framework 3.5) >ASP.net Web Service Application
This will create a web service with a HelloWorld example like
public string HelloWorld()
{
return "Hello World";
}
2. Create a Database and Obtain the connection string
3. Define WebMethod
To create a new method that can be accessed by clients over the network,create functions under [WebMethod] tag.
4.Common structure for using database connection
add using statements like
using System.Data;
using System.Data.SqlClient;
Create an SqlConnection like
SqlConnection con = new SqlConnection(#"<your connection string>");
create your SqlCommand like
SqlCommand cmd = new SqlCommand(#"<Your SQL Query>", con);
open the Connection by calling
con.Open();
Execute the query in a try-catch block like:
try
{
int i=cmd.ExecuteNonQuery();
con.Close();
}
catch (Exception e)
{
con.Close();
return "Failed";
}
Remember ExecuteNonQuery() does not return a cursor it only returns the number of rows affected,
for select operations where it requires a datareader,use an SqlDataReader like
SqlDataReader dr = cmd.ExecuteReader();
and use the reader like
using (dr)
{
while (dr.Read())
{
result = dr[0].ToString();
}
dr.Close();
con.Close();
}
Here is a video that will walk you through how to retrieve data from MS SQL Server in ASP.NET web service.
I am using SQLCacheDependency in my ASP.NET application with Query Notifications.
I followed this article to set up my database with success.However whenever I am trying to store data in the cache object.It just does not hold value.It is always null .I am not getting any errors or exceptions.
Here is my code
Global.asax
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
System.Data.SqlClient.SqlDependency.
Start(ConfigurationManager.ConnectionStrings["McdConn"].ToString());
}
void Application_End(object sender, EventArgs e)
{
// Code that runs on application shutdown
System.Data.SqlClient.SqlDependency.
Stop(ConfigurationManager.ConnectionStrings["McdConn"].ToString());
}
public static class CacheManagement
{
public static DataTable CreateCache(string cacheName, string tableName, string query)
{
DataTable dtResult = new DataTable();
try
{
string connectionString = ConfigurationManager.ConnectionStrings["McdConn"].ToString();
dtResult = HttpContext.Current.Cache[cacheName] as DataTable;
if (dtResult == null)
{
dtResult = new DataTable();
using (var cn = new SqlConnection(connectionString))
{
cn.Open();
var cmd = new SqlCommand(query, cn);
cmd.Notification = null;
cmd.NotificationAutoEnlist = true;
SqlCacheDependencyAdmin.EnableNotifications(connectionString);
if (!SqlCacheDependencyAdmin.GetTablesEnabledForNotifications(connectionString).Contains(tableName))
{
SqlCacheDependencyAdmin.EnableTableForNotifications(connectionString,tableName);
}
var dependency = new SqlCacheDependency(cmd);
//SqlDataAdapter ad = new SqlDataAdapter(cmd);
//ad.Fill(dsResult);
SqlDataReader reader = cmd.ExecuteReader();
dtResult.Load(reader);
HttpContext.Current.Cache.Insert(cacheName, dtResult, dependency);
}
}
}
catch (Exception ex)
{
Exception_Log.ExceptionMethod("Web", "CacheManagement.cs", "CacheManagement", ex);
}
return dtResult = HttpContext.Current.Cache[cacheName] as DataTable;
}
}
Code Behind
var dtCachedCategories = HttpContext.Current.Cache["tbl_CategoryMaster_Cached"] as DataTable;
if (dtCachedCategories == null)
{
dtCachedCategories = CacheManagement.CreateCache("tbl_CategoryMaster_Cached","dbo.tbl_CategoryMaster_Languages", "Select * from dbo.tbl_CategoryMaster_Languages");
}
The above always returns null.
Can anyone help me in pointing out what could be missing?
Well there's a lot you can do to debug your code and arrive at a conclusion. It seems like your cached item is getting removed too frequently.
1.) Use CacheItemPriority.NotRemovable to Cache.Insert() to make sure ASP.NET doesn't removes
your item whenever it feels so. use the Insert() method explained here. Check this MSDN
article too.
2.) To find out the reason why your cached item is getting removed , log this removal action using
CacheItemRemovedCallback delegate option of your Cache.Insert() method. Check this Insert method
overload version and also this link.
3.) Make sure your dtresult as well as your reader is not null. Check the lines:
SqlDataReader reader = cmd.ExecuteReader(); & dtResult.Load(reader); , together with your logs.
4.) Check your application Pool recycle time. This link has everything related to App pool settings ( IIS 7 +).
5.) This link has a solution for App pool of IIS 6: http://bytes.com/topic/net/answers/717129-c-asp-net-page-cache-getting-removed-too-soon
Also, try using HttpRuntime.Cache method to see if it works.
System.Web.HttpRuntime.Cache.Insert(cacheName, dtResult, dependency);
I have an ASP.NET web page. It makes use of 4 BackgroundWorkers. Each bw retrieves some data from a database.
The code for connecting to the database is:
if (dbConnection.State == ConnectionState.Closed)
{
dbConnection.Open();
}
DataTable dt = new DataTable();
OdbcCommand cmd = new OdbcCommand(sqlQuery, dbConnection);
cmd.CommandTimeout = 0;
IDataReader dataReader = cmd.ExecuteReader();
dt.Load(dataReader);
dataReader.Close();
dataReader.Dispose();
In the constructor, this.dbConnection = new OdbcConnection(networkdetails);
Each bw makes use of the above code snippet to query the database and retrieve the values. The code works perfectly fine sometimes. Other times it throws the exception given above.
Any help as to what I may be doing wrong?
Try to handle the exception and then close the connection.
For this, write your code in 'Try' block, catch the exception in 'Catch' block and close the connection in 'Finally' block.
try{
// Your code
}
catch
{
// Catch exception
}
Finally
{
// Close the connection
dbConnection.Close();
}
Let say i have one asp.net application that is having some page that uses the connection continuesly.....
i have open the connection in class file in construscter ......
and i m accessing it using the object of the class....when ever database operation are required...
in start the application is running fine....but after some operation with database in datagrid(ex. sorting,paging,other).... it's gets slow...and again start working after some time....
do you guys have any solution or any suggession for that.....
i have used the connection in following way....
public class student_operation
{
public SqlConnection cn = new SqlConnection();
public SqlCommand cmd = new SqlCommand();
public SqlDataAdapter ad = new SqlDataAdapter();
public DataSet rs = new DataSet();
public DataSet rs1 = new DataSet();
public student_operation()
{
//
// TODO: Add constructor logic here
//
try
{
cn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["myconnection"].ConnectionString);
cn.Open();
}
catch (Exception)
{
if (cn.State != ConnectionState.Closed)
{
cn.Close();
cn.Open();
}
}
}
}
Make sure you are opening AND closing your connection. Don't worry about "pooling" the connection. .Net will handle that for you automatically. Just open the connection, do your work and close the connection (even if that's done in the static part).
I don't see where you are closing your connection. I would implement IDisposable and clean everything up there. Then you can access your class in a using statement.