How to refresh ASP.NET Cache when data is updated in database? - asp.net

I am currently leveraging the code below to refresh a cache at midnight every day. It works great, but the requirements are going to change such that I need to update the cache when an item in the dataset changes. I understand that there is a CacheDependency class for checking to see if a file has changed in order to refresh the cache - but I don't see how that applies to what I am trying to do. Can someone help steer me in the right direction for updating the cache when the dataset changes? Thanks.
try
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["localDb"].ConnectionString);
DataSet ds = new DataSet();
if (Cache["ds"] == null)
{
conn.Open();
SqlCommand sqlComm = new SqlCommand("SELECT EmployeeID, NationalIDNumber, ContactID, LoginID, ManagerID, Title, BirthDate, MaritalStatus, Gender FROM HumanResources.Employee", conn);
SqlDataAdapter adapter = new SqlDataAdapter(sqlComm);
adapter.Fill(ds);
Cache.Insert("ds", ds, null, DateTime.Today.AddDays(1), TimeSpan.Zero);
conn.Close();
}
GridViewEmployees.DataSource = (DataSet)Cache["ds"];
GridViewEmployees.DataBind();
}
catch (Exception)
{
throw;
}

DotNet 2.0+ approach
I suppose you've heared and read about SqlCacheDependency class, haven't you? Well if you haven't I suggest you do. It will bring a smile on your face. ;)
MSDN article.
DotNet 1.x approach
In the old days (pre .net 2.0 and pre SQL 2005) there was also a trick with usual CacheDependency class in a way so that you created a trigger for inserts/updates on the table that needed it that barely (re)saved an empty file (so it was as fast as possible) in some folder and you depended your cache on that particular file hence getting your cache invalidated when data changed. As I heard it worked fine.
MSDN Magazine article from 2003 about it.

Related

ASP.NET Pros and Cons of two different ways of displaying data on website

I know of two ways to display data on a website.
The first is by using adding a DB connection to the Server Explorer and then dragging the table you want to display on the webpage. Visual Studio does all the backend stuff for you.
The second is where you just choose the control you want to use and you hook it up manually through code for it to display the data you want. You do not have to connect to the DB in server explorer. Something like this in code behind:
SqlConnection sqlConnection = new SqlConnection(connString);
SqlCommand command = new SqlCommand("RawToSummary", sqlConnection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#SDate", SqlDbType.Date).Value = MySDate;
command.Parameters.Add("#EDate", SqlDbType.Date).Value = MyEDate;
sqlConnection.Open();
command.ExecuteNonQuery();
sqlConnection.Close();
private DataTable FillData(string connString, SqlCommand cmd)
{
SqlConnection conn = new SqlConnection(connString);
DataTable dt = null;
try
{
cmd.Connection = conn;
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
SqlCommandBuilder cb = new SqlCommandBuilder(da);
DataSet ds = new DataSet();
da.Fill(ds, "tableName");
dt = ds.Tables["tableName"];
}
catch (Exception e)
{
WriteLog("Error: " + e);
}
finally
{
conn.Close();
}
return dt;
}
I have 2 questions:
1) What is the second method called? I am trying to learn more about it but need a Google search term for it.
2) What are the pros and cons of each method?
I am using the following: Visual Studio 2010, SQL Server Management Studio 2008
Server Explorer/Database Explorer is the server management console for Visual Studio. Use this window to open data connections and to log on to servers and explore their system services.
With Server Explorer/Database Explorer we can view and retrieve information from all of the databases connected to. like:
List database tables, views, stored procedures, and functions
Expand individual tables to list their columns and triggers
Right-click a table to perform actions, such as showing the table's
data or viewing the table's definition, from its shortcut menu.
Programmatic approach
Second approach is the programmatic approach to perform the DM (data manipulation) and DD (data definition) functions.
Server Explorer/Database Explorer goes through the same course (connecting with database, query tables etc.) but in the background while in programmatic approach we write commands (queries/stored procedures) for the same.
I hope this gives an idea.

oracleDatareader.ExecuteReader() not returning any data

I have written a code in ASP.NET to fetch data from Oracle database. The code returns data from locally hosted Oracle DB but when I am pointing towards the remote OracleDB, nothing comes. However, if I run same query on the remote DB using SQL Developer Tool, it works fine.
I have debugged my code for right SQL statement and it is absolutely correct.
Following is my code snippet
using (Oracle.DataAccess.Client.OracleConnection con = new
Oracle.DataAccess.Client.OracleConnection())
{
con.ConnectionString = ConfigurationManager.ConnectionStrings["ca_eFormsVSED"].ConnectionString;
con.Open();
// query for fetch username and market
String sql = "a valid query"
Oracle.DataAccess.Client.OracleCommand cmd = new Oracle.DataAccess.Client.OracleCommand(sql, con);
cmd.CommandType = CommandType.Text;
if (con.State == ConnectionState.Open)
{
Oracle.DataAccess.Client.OracleDataReader dr = cmd.ExecuteReader();
}
if (dr.Read())
{
//Do Something
}
}
Please suggest how to make it work.
I got the solution of this problem and it may help some one else. If you are 100% sure that code is correct and current SQL statement returns data from database, then check carefully your database tables have dependency or not. Remove existing tables and import new data again and it works fine for me.

How to use SQL-Server Stored Procedures?

over the past week or so I've been building an ASP site that connects to a Sql-Server 2008 database. I've never used Stored procedures and I was wondering if anyone could give me some guidance on how to create and how to use them within an ASP method. I'm trying to make the code of the website as simple and elegant as possible. Here's the code I'm trying to change into a stored procedure:
private void ExecuteInsert(string name, string type)
{
SqlConnection conn = new SqlConnection(GetConnectionStringHM());
string sql = "INSERT INTO tblSoftwareTitles (SoftwareName, SoftwareType) VALUES "
+"(#SoftwareName,#SoftwareSystemType)";
try
{
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
SqlParameter[] param = new SqlParameter[2];
//param[0] = new SqlParameter("#SoftwareID);
param[0] = new SqlParameter("#SoftwareName", SqlDbType.NVarChar, 200);
param[1] = new SqlParameter("#SoftwareType", SqlDbType.Int);
param[0].Value = name;
param[1].Value = type;
for (int i= 0; i < param.Length; i++)
{
cmd.Parameters.Add(param[i]);
}
cmd.CommandType = CommandType.Text;
cmd.ExecuteNonQuery();
}
catch (System.Data.SqlClient.SqlException ex)
{
string msg ="Insert Error:";
msg += ex.Message;
throw new Exception(msg);
}
finally
{
conn.Close();
}
}
This is just a Simple insert that takes two parameters from an entry form and inserts them into the database. Any Help with this would be much appreciated as I feel it would be a useful thing to know later on down the line. Thanks in advance!
You should look in to MSDN basics: http://msdn.microsoft.com/en-us/library/bb896274.aspx
You don't need to complicate things using for loop.
try
{
sqlConnection = new SqlConnection(dbConnectionString);
SqlCommand command = new SqlCommand(sql, sqlConnection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#SoftwareName", SqlDbType.NVarChar, 200).Value = SoftwareNameHere;
command.Parameters.Add("#SoftwareType", SqlDbType.Int).Value = SoftwareTypeHere;
sqlConnection.Open();
return command.ExecuteNonQuery();
}
catch (SqlException ex)
{
Console.WriteLine("SQL Error" + ex.Message.ToString());
return 0;
}
finally
{
conn.Close();
}
If you are using .NET 3.5 or above, you can use the USING code block which takes care of the disposal of your resources. I am not entirely sure, but from what I remember this was introduced with .NET 3.5 to replace Try/Finally code block (which required developers to dispose the resources like connection object manually through code).
using (SqlConnection con = new SqlConnection { dbConnectionString })
{
con.Open();
try
{
using (SqlCommand command = new SqlCommand { CommandType = CommandType.StoredProcedure, Connection = con, CommandTimeout = 300, CommandText = "sp_Test" })
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#SoftwareName", SqlDbType.NVarChar, 200).Value = SoftwareNameHere;
command.Parameters.Add("#SoftwareType", SqlDbType.Int).Value = SoftwareTypeHere;
command.ExecuteNonQuery();
}
}
catch(SqlException ex)
{
//ex.ToString message here;
}
}
The answer you're looking for is at this SO post...
https://stackoverflow.com/a/4561443/1246574
The one thing I would improve upon for the accepted answer in that post, is the example in that answer doesn't use any USING statements. It would be better to have the connection and command within USING statements so they are automatically disposed.
Another approach would be to use the Microsoft Enterprise Library for interacting with your SQL Server DB. I think it's easier than using plain old SqlConnection and SqlCommand.
Since your code already uses parameters, you are 90% of the way there. All you have to do is:
Put the insert statement into a stored procedure, keeping the same parameter definitions as the dynamic statement.
Change CommandType.Text to CommandType.StoredProcedure
Change the command text to be just the name of the stored procedure.
Having done some reading on the subject I've come across some useful articles that really do question my need for stored procedures.
This article gives a good Viewpoint on how stored procedures can be more of a hassle than a help and are quite clunky and tedious in terms of coding, debugging ad error reporting.
http://www.codinghorror.com/blog/2004/10/who-needs-stored-procedures-anyways.html
And this article (linked in the one above) gives a good explanation on parametrized, explaining why they are necessary to reduce the risk of sql injections and also raises the point that these parametrized queries are cached in a similar way to procedures, giving them comparable performance gains
http://www.uberasp.net/getarticle.aspx?id=46
I feel that In my situation keeping parametrized sql Queries coded into my ASP pages will be the smartest move as these pages will be stored on a server and accessed by clients. I imagine if this were an application installed on several client machines hard coding the SQL wouldn't be a desirable option and so Stored procedures would be the best way to go (to my knowledge)
A follow Up to Stored procedures verses Parametrized sql can be found here with different links to each side of the argument if those are interested.
http://www.codinghorror.com/blog/2005/05/stored-procedures-vs-ad-hoc-sql.html
Hope this little answer helps out anyone else considering using stored procedures over parametrized SQL and vice-versa

MySqlDataAdapter failed to retrieve data on the first load

I use MySQL Connector for ASP.NET to retrieve data from my MySQL server. Everything seems to work fine, but just at the first asynchronous postback of my page, MySQLDataAdapter does not fill my DataSet. After a complete refresh the data is succesfully loaded by asynchronous postback.
I try to assign a bigger value to the command timeout, but it does not seem seem to work.
This does not happen locally, only on the production server.
I have checked that the fill does not work by displaying the request string and also by on each async postback (displaying the count() of my DS.table[0].rows).
This is really the fill method not working.
try
{
using (MySqlConnection conn = new MySqlConnection(_connexionString))
{
string requete = "";
DataSet DS = new DataSet();
requete = "SELECT * from MYTABLE";
using (MySqlDataAdapter MSDA = new MySqlDataAdapter(requete, conn))
{
DS.Clear();
MSDA.Fill(DS);
}
conn.Close();
conn.Dispose();
}
}
catch (MySqlException ex)
{
l_error.Text = ex.ToString();
}
Try putting code into Page_Init event too.
did you checked Page.isPostBack property ? may be you are not checking isPostback, properly. it would be helpful,if you share your entire method.
if(!Page.IsPostBack)
{
//load your datasets and data - adapters.
}
After few investigation in code, i found that it not work, in fact an value of request was empty ... so no data return by mysql server, there was session key which was expire...
thx all for your help !

SqlCacheDependency not working

I would like to add SqlCacheDependency to my app.
So I desided to create littel tesp project and confronted with difficulties.
I use MSSQL 2008. I create new db with table Lines and added several rows.
I executed:
ALTER DATABASE ForTest SET ENABLE_BROKER
in managmeng studio.
Aspx page:
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (Cache["Lines"] == null)
{
string connectionString =
WebConfigurationManager.ConnectionStrings["ForTest"].ConnectionString;
SqlConnection con = new SqlConnection(connectionString);
string query = "SELECT dbo.Lines.Id, dbo.Lines.Value FROM dbo.Lines";
SqlCommand cmd = new SqlCommand(query, con);
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
adapter.Fill(ds, "Lines");
SqlCacheDependency empDependency = new SqlCacheDependency(cmd);
Cache.Insert("Lines", ds, empDependency);
}
}
}
protected void btnResult_OnClick(object sender, EventArgs e)
{
var result = Cache["Lines"];
}
}
I run this page and add lines to Cache then I add row in managment studio and when I click on button I expect
that the cache will be changed but cache remains old.
I can't find what I do wrong :( Could you give me some hint how I can solve this problem?
Thanks
Update:
I forger to say that in global.aspx I run:
SqlDependency.Start(
WebConfigurationManager.ConnectionStrings["ForTest"].ConnectionString
);
I had a similar issue. This article: Troubleshooting SqlCacheDependency in SQL Server 2008 and SQL Server 2005 helped me a lot then.
In a few words: the databse was restored from a backup, and the original Windows user that created the database was no longer available. So I changed the database ownership to a valid login, something similar to:
ALTER AUTHORIZATION ON DATABASE::[my_perfect_database_name] TO [sa];
and it works like a charm now.
How did I find the source of the issue? I run the query SELECT * FROM sys.transmission_queue and found the next data in the transmission_status column:
An exception occurred while enqueueing a message in the target queue.
Error: 15517, State: 1. Cannot execute as the database principal
because the principal "dbo" does not exist, this type of principal
cannot be impersonated, or you do not have permission.
This message gave me a key to solving the problem.
There is a mistake in the code;
Definition of sqldependency should be placed before you execute the command,
otherwise it will not subscribe to your sqlcommand, then it won't get notified when your resultset of your command changes.
SqlCacheDependency empDependency = new SqlCacheDependency(cmd);
DataSet ds = new DataSet();
adapter.Fill(ds, "Lines");
I also thought I had an issue with the SqlCacheDependency not being cleared after a change to the table.
Turns out it was because of how I was testing. I was simply editing the rows in the SQL table thru management studio and expecting it to notify and clear the cache. That's not the case! If you are editing the table, you must also re-execute the select sql to kick off the clearing of the cache.

Resources