SqlCacheDependency not working - asp.net

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.

Related

Why doesn't TransactionScope start a transaction for my following SQL commands

I set up a using block for a TransactionScope at the beginning of an ASP.NET action. Somewhere w/i the block I execute a function that both creates a using block for a SqlCommand and w/i that a using block for my SqlConnection.
The blocks for the command and connection open and close as the function is re-used but all w/i the TransactionScope using block. Eventually I call scope.Complete() and when leaving the TransactionScope using block I get an exception saying that no transaction was started that can be committed. In debugging I find that in fact all database calls are just happening w/o a transaction.
Based off the documentation its seeming like the generation of the TransactionScope should be the generation of the transaction, OR, at least that the first time I open any database connection that a transaction should begin because it's w/i the transaction scope block. However this is not the case and I'm unsure why this is.
I actually had this working fine at one point and then all of a sudden, it was not working. So there's something that I did that caused it but I have no idea what it was as the section this was implemented in was completed long ago.
Here's some code:
Starting the transactionScope
using (TransactionScope transactionScope = new TransactionScope())
{
try
{
LegacyDataManager.Start();
//*******************Replace W/ Controller Logic*********************
ViewBag.Message = "Finish";
...
...
...
LegacyDataManager.Commit();
transactionScope.Complete();
}
finally
{
LegacyDataManager.Stop();
}
}
Call to code that executes database update
var theApproval = LegacyDataManager.PrepareForUpdate(Constants.ObjectApproval, row["objectInstance"].ToString(), row["sourceServer"].ToString());
theApproval.write("approvalaction", Request.Form[val].ToString().Substring(0, 1));
theApproval.write("approvaldate", Data_Legacy.getAodDateTimeNow());
theApproval.saveObject();
The database query execution
Data.executeSP("sp_Object_InsertData", SearchNew.generateSQLParameterString("ObjectType", "ObjectInstance", "Parameter", "ParameterValue", "SourceServer"),
SearchNew.generateSQLParameterString(
ObjectType,
ObjectInstance.ToString(),
theNametext,
Regex.Replace(thetheVal, #"\'", "\'\'").Trim(),
SourceServer));
public static DataTable executeSP(string storedProc, SqlParameter[] parms = null, bool gatherParams = true, int commandTimeout = 0)
{
using (SqlCommand cmd = new SqlCommand())
{
if (commandTimeout != 0)
{
cmd.CommandTimeout = commandTimeout;
}
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = storedProc;
handleParameters(cmd.Parameters, storedProc, parms, gatherParams);
using (SqlConnection conn = Data.getConnection("AOD"))
{
if (conn.State != ConnectionState.Open)
conn.Open();
cmd.Connection = conn;
var da = new SqlDataAdapter();
var dt = new DataTable();
da.SelectCommand = cmd;
da.Fill(dt);
return dt;
}
}
}
Thanks for any suggestions in advance.
The good news is that this can just be removed but the bad news is that it creates an annoying programming environment where the XML data files this system is based don't get updated during an error but the updated SQL data that is mirrored out to is retained... Don't ask why that's how it is... it just is.
Apparently I had added a try/catch block around a function that ran a Stored procedure because the data being passed in would sometimes need the function and sometimes not (and thus fail, hence the try catch). Unfortunately when the db call failed the transaction associated w/ the TransactionScope was dropped and the try catch kept the program going.
I removed the the try catch block and replaced it w/ a check on the data passed into the function before determining whether or not to execute the Stored Procedure and now it is once again operating properly.
TL;DR - Check to see if any database calls are failing w/i the transactionScope as it might lead to dropping of the transaction.

Proper Protocol for Connecting to Azure SQL DB for ASP.NET Web Forms Site

New to ASP.NET trying to connect to an Azure SQL DB. I don't know exactly what to include in the connection string. I've viewed many posts from this site but a lot of the answers have different content in the connString.
The following is my Form_Load event handler code:
protected void Page_Load(object sender, EventArgs e)
{
//declare connection sting for Azure SQl DB
string strSQLconnection = "Data Source=someValue.database.windows.net;Initial Catalog=dbName;Integrated Security=True";
//create SqlConnection object and pass strSQLconnect variable from above as parameter
SqlConnection sqlConnection = new SqlConnection(strSQLconnection);
//create SqlCommand object and select table EMPLOYEES from Azure DB for grid view (to test) and pass sqlConnection from above as parameter
SqlCommand sqlCommand = new SqlCommand("select * from Employees", sqlConnection);
//open the SQL connection
sqlConnection.Open();
//create SqlDataReader object to be able to read from Azure DB
SqlDataReader reader = sqlCommand.ExecuteReader();
gvAzureSql.DataSource = reader;
gvAzureSql.DataBind();
}
Note: I added the gridView just for testing purposes to see if data has been binded; wont be on implemented form.
Also, Im using the address on the top left of the Azure db site; is this correct (########.database.window.net)
I've seen solutions advising to add connection string tag in web.config. Do I also have to do this. If so, may you provide the proper protocol to set this up for Azure SQL DB. I've searched for a long time and can't find a definitive question or process of exactly what to enter in the connString.
Thanks

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 !

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

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.

How do I execute an INSERT using SqlCommand?

I have another class that creates the connection (see refined class half way down page) and I believe it connects or at lest I do not hit any of the exceptions in run time.
I would now like to insert data into my database but nothing is updated.
I am trying to follow this example but it is for reading.
I did run "querystring" on the show SQL Pane and it does execute correctly. It inserts data properly as a new row.
not sure what to do after my last line? Thanks.
string queryString =
"INSERT INTO UserData UserProfileID, ConfidenceLevel, LoveLevel, HappinessLevel) VALUES ('a051fc1b-4f51-485b-a07d-0f378528974e', 2, 2, 2);";
protected void Button1_Click(object sender, EventArgs e)
{
MySqlConnection database = new MySqlConnection();
database.CreateConn();
Command = new SqlCommand(queryString, database.Connection); //
}
Command.ExecuteNonQuery();
By the way, you're missing a parenthesis in your SQL query string.
And of course, you'd use parameters in a real query (and you will not use string concatenation instead of passing parameters as it'll open doors for destructive SQL injection attacks).

Resources