I'm developing website with query notification using SqlCacheDependency. When the website loads for the first time, if there is any cache, it retrieves the data from the cache while the opposite, if there is no cache, it retrieves data from database and then insert the cache.
When the user inserts data, and clicks a button, the website stores the data to the database, removes the cache, so when the page redirects to itself, there is no cache, which makes the website should retrieve the new data.
Here is the following code:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
return;
this.BindGrid();
System.Diagnostics.Debug.WriteLine(Cache.Count);
//cache counts : -4; I don't even know why
}
protected void btnSave_Click(object sender, EventArgs e)
{
this.Insert(this.txtTitle.Text, Convert.ToInt32(this.txtDescription.Text));
//insert just function to update the database
Cache.Remove("Messages");
this.BindGrid();
}
private void BindGrid()
{
DataTable dtMessages = (DataTable)Cache.Get("Messages");
if (dtMessages == null)
{
dtMessages = this.LoadMessages();
lblDate.Text = string.Format("Last retrieved DateTime : {0}", System.DateTime.Now);
}
else
{
lblDate.Text = "Data Retrieved from Cache";
}
grdMessages.DataSource = dtMessages;
grdMessages.DataBind();
}
private DataTable LoadMessages()
{
DataTable dtMessages = new DataTable();
dtMessages = new DataTable();
using (SqlConnection connection = new SqlConnection(this.ConnectionString))
{
SqlCommand command = new SqlCommand("select * from blablabla", connection);
SqlCacheDependency dependency = new SqlCacheDependency(command);
if (connection.State == ConnectionState.Closed)
connection.Open();
dtMessages.Load(command.ExecuteReader(CommandBehavior.CloseConnection));
if (Cache.Get("Messages") == null)
{
Cache.Insert("Messages", dtMessages, dependency);
}
}
return dtMessages;
}
The problem is, looks like the cache hasn't been made/inserted. Because the value of Cache.Count is negative number. And whenever I just refresh the page (where the page supposed to retrieve data from cache), the page retrieves the data from database.
What's wrong and what is the solution? There are two important things to know:
Page only retrieves from database when there is no cache (cache'll be removed when user inserts data)
Page retrieves from cache when there is no any updated/new data from user (e.g. user just refreshes the page, page retrieves from cache)
Please help. Thank you for your time and attention.
Related
I have a web form page that I am going to query the data from database via selecting different values from dropdown list, after I selected proper value, in the description I want to update the database record while I click the submit button, for example, customer name, and status, there will be only one record coming back and the description will show(I can do it in isPostback and query the database, using SQL DataReader and then call related index element to get it) but when I typed something in the description and click submit, it won't update in the database, but if I don't use if(isPostback) it is working.
P.S. if there is no if(ispostback) case block there,dataUpdate.Update() works well.
So my question is;
protected void btnSubmit_Click(object sender, EventArgs e)
{
dataUpdate.Update();
}
The page_load code:
protected void Page_Load(object sender, EventArgs e)
{
ValidationSettings.UnobtrusiveValidationMode = UnobtrusiveValidationMode.None;
if (!IsPostBack)
{
SqlConnection conn1 = new SqlConnection(cxInfo.ConnectionString);
string userInfoQuery1 = "select * from users where id=#id";
SqlCommand userInfo1 = new SqlCommand(userInfoQuery1, conn1);
userInfo1.Parameters.AddWithValue("#id", dropdlCx.SelectedValue);
conn1.Open();
SqlDataReader reader1 = userInfo1.ExecuteReader();
reader1.Read();
if (reader1.HasRows )
{
lblCxId.Text = "" + reader1[0];
SqlConnection conn = new SqlConnection(dataUpdate.ConnectionString);
string userInfoQuery = "select cx_first_name+',' + cx_last_name as 'name',cx_id ,incident_id,description,contact_method from incident where cx_id=#id and status=#status";
SqlCommand userInfo = new SqlCommand(userInfoQuery, conn);
userInfo.Parameters.AddWithValue("#id", lblCxId.Text);
userInfo.Parameters.AddWithValue("#status", dropStatus.SelectedValue);
conn.Open();
SqlDataReader reader = userInfo.ExecuteReader();
reader.Read();
if (reader.HasRows)
{
lblCxId.Text = "" + reader1[0];
txtDesc.Text = (string)reader[3];
radioContact.SelectedValue = (string)reader[4];
desc= (string)reader[3];
}
conn.Close();
}
conn1.Close();
}
if (IsPostBack)
{
lblCxId.Text = dropdlCx.SelectedValue;
/*I want to have txtDesc.txt= database query here, but as long as I add the code here, then the update won't work*/
}
}
So I think there only thing I got stuck is how to let the system know that what I submit is not the thing that he is going to refresh, please accept my value instead of the refresh?
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 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 am using Visual studio and have the following page_load function on my Default.aspx web form:
if (IsPostBack == false)
{
//Display all records on the form load
DisplayCars("");
I have a user, where I can get their username (which I have used to add as the "Creator" of the specific data record). I want to use this username to only display cars where the username = ACar.Creator
How would I go about doing this? I have everything setup in order to do this.
I need something like the following:
if (User.Identity.Name == ACar.Creator) {
show this record
}
But I do not know the syntax for this within aspx/sql
Thanks
You should actually do this in the database by passing username
public DataTable GetUserRecord(string userName)
{
DataTable dt = new DataTable();
SqlConnection conn = new SqlConnection("connection string to database");
using(conn)
{
string sql = "SELECT car.CarName, car.Model FROM car WHERE car.Creator = #UserName";
SqlCommand comm = new SqlCommand(sql, conn);
comm.Parameters.AddWithValue("#UserName", userName);
dt.Load(comm.ExecuteReader());
}
return dt;
}
From your page
protected void Page_Load(object sender, Eventargs e)
{
DataTable dt = GetUserRecord(User.Identity.Name);
if(dt.Rows.Count > 0)
{
string firstRowCarName = dt.Rows[0]["CarName"];
//etc
}
}
I have a formview that on page load makes a call to a sql server and retrieves 5 records which I want the formview to paginate though.
I have sucessfully connected to the db, filled a dataset, and returned data when the web page renders. The problem is that when I move to a new page, the data does not change in the databound field.
Here is my code:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
conn = new SqlConnection(connstr);
ds = new DataSet();
da = new SqlDataAdapter("call to stored proc", conn);
try
{
conn.Open();
da.Fill(ds, "m");
FormView1.DataSource = ds;
FormView1.DataKeyNames = new string[] { "PropKey" };
FormView1.DataBind();
}
catch (Exception ex)
{
Result = ex.Message;
}
finally
{
conn.Close();
}
}
Next when the paginate buttons are clicked I have this:
protected void FormView1_PageIndexChanging1(object sender, FormViewPageEventArgs e)
{
FormView1.PageIndex = e.NewPageIndex;
}
Please help,
Thanks
You will need to bind the data to the FormView just after setting the new page index like below.
protected void FormView1_PageIndexChanging1(object sender, FormViewPageEventArgs e)
{
FormView1.PageIndex = e.NewPageIndex;
BindFormViewData();
}
This is required because the FormView only displays the data for the active record and does not store any other records from the datasource, so upon change of the page index, the datasource is required to be bound again. See: Paging in a FormView Web Server Control
From the above link:
If the FormView control is bound to a data source control, or to any
data structure that implements the ICollection interface (including
datasets), the control gets all the records from the data source,
displays the record for the current page, and discards the rest. When
the user moves to another page, the FormView control repeats the
process, displaying a different record.
Hope this helps.