The Problem:
No matter how sure I am that my transactions are committed and the application can read the absolute latest from the database, sometimes when I refresh the application the changes aren't displaying the latest data and I suspect that the data is being cached in the browser! This suspicion comes from loading the web application in another browser after the changes are made and seeing the changes. I need to make it so that every time the page is refreshed, this data is not cached in the browser.
Setup:
One Web Application simply reads from the database, while AJAX calls are made client side to a REST API that adds, deletes, and updates the data.
I have been doing a lot of research and the most valuable resource I have found on this was here: http://mehdi.me/ambient-dbcontext-in-ef6/
My code that reads from the database uses this pattern:
public IEnumerable<Link> GetLinks(){
using (var context = new MyContext()){
foreach(var link in context.ChangeTracker.Entries())
{
link.Reload();
}
return context.Links.Where(x => x.UserId == this.UserId).ToList();
}
}
An example of one of my operations that reads follows this pattern:
public int AddLink(string text, string url)
{
using (var context = new MyContext())
{
Link linkresult;
using (var contextTransaction = context.Database.BeginTransaction())
{
var link = new Link()
{
Text = text,
Url = url
UserId = this.UserId
};
linkresult = context.Links.Add(link);
context.SaveChanges();
contextTransaction.Commit();
}
return linkresult.Id;
}
}
Now as shown above, the context.SaveChanges() with the contextTransaction.Commit() I'm making sure that the data gets written to the database and is not cached at any level. I have confirmed this by using the Server Explorer and watching the content get updated real time.
I also think I have confirmed that my read will pull up the latest information from the database by loading the web application in another browser after the changes have been made, but I acknowledge that this may also be a caching issue that I am not aware of.
My last step is getting around the caching that happens in the browser. I know chrome allows you to clear your app hosted data, but I don't know how to make certain data is not cached so that every time a request happens this code executes.
More Details on the REST API: The Controller for the above example looks something nearly identical to this:
public ActionResult AddLink(MyLink model)
{
IntegrationManager manager = new IntegrationManager(System.Web.HttpContext.Current.User);
model.Id = manager.AddLink(model.Text, model.Url);
return Json(model);
}
The IntegrationManager is just a basic class that does not implement IDisposable because the context is created and disposed of during each transaction. As can be seen, the AddLink is a member of the IntegrationManager class.
More Details on the Web Application: The model for the view creates an IntegrationManager in it's constructor as a temporary variable to make the getLinks call as follows:
public Home(IPrincipal user, Cache cache)
{
this.HttpCache = cache;
IntegrationManager _IntegrationManager = new IntegrationManager(user);
this.Links = this.GetLinks(_IntegrationManager);
}
AJAX Call:
.on("click", "#btn-add-link", function (event) {
var text = $("#add-link-text"),
url = $("#add-link-url");
if (text.val().length > 0 && url.val().length > 0) {
var hasHttp = /^http.*$/.test(url.val());
if (!hasHttp) {
url.val("http://" + url.val());
}
$.ajax({
url: addLinkUrl,
type: "POST",
data: { Text: text.val(), Url: url.val() }
}).success(function (data) {
var newLink = $('<li class="ui-state-default deletable" id="link-' + data.Id + '"><a href="' + data.Url + '" target="_blank">' + data.Text + '</a></li>');
$("#user-links").append(newLink);
text.val("");
url.val("");
});