ASP.NET MVC database dependency cache

ASP.NET MVC database dependency cache

 

problem background

 

A very simple function I have recently made is to request a piece of data from a drop-down table from the server using an ajax request.

 

This function has been done before, but an idea came up when doing this function this time:

 

The piece of data I requested is a relatively fixed piece of data, that is to say, it does not change much, maybe only once a few months.

 

Because the change cycle of this kind of data is very long, when this function was used in the past, the cache was used for optimization, and the data could be read directly from the cache, avoiding the need to ask the database for data every time an ajax request was received, reducing the The interaction between the server and the database reduces the pressure on the database server.

 

But here comes the problem. No matter how long the data change cycle is, it will change. When the data in the database changes, you have to remove the old cached content. Okay, I used to do this. of:

 

public ActionResult GetAllFJs()

{

    // try to fetch data from cache

    var FJIdNames = HttpContext.Cache["FJIdNames"];

    if (null == FJIdNames) //There is no data in the cache

    {

        //Query data from database

        FJIdNames = FJService.GetAll().Select(fj => new { Id = fj.Id, Name = fj.Name }).ToArray();

        //Cache the data for next use (set a cache valid time, use absolute expiration, reach the specified expiration time, cache invalidation)

        HttpContext.Cache.Insert(

                                  "FJIdNames", //The key of the cache item (string)

                                  FJIdNames, //The value of the cache item (object)

                                  null,         

                                  DateTime.UtcNow.AddMinutes(30), //absolute expiration time (DateTime)

                                  System.Web.Caching.Cache.NoSlidingExpiration //Sliding expiration interval (TimeSpan)

                                );

    }

 

    //Convert the obtained data into a json format string

    string jsonResult = CommonHelper.ConvertToJsonStr(FJIdNames);

    //result string returned to the browser

    return Content(jsonResult);

}

 

Description: This is an action method for processing a request in asp.net MVC, which has an important method

 

public void Insert(

  string key, --> the key of the cache item

  object value, --> the value of the cache item

  CacheDependency dependencies, --> Cache dependencies (not used here, will be used later, it is the highlight)

  DateTime absoluteExpiration, --> absolute expiration time point

  TimeSpan slidingExpiration --> sliding expiration interval

);

 

Here, the cached expiration time is used to update the cached data. Whenever the cached data passes 30 minutes, it is necessary to re-fetch the data from the database to update the content in the cache, and take a look at the execution result (in order to To facilitate the display of results, adjust the absolute expiration time to 30s):

 

First request:

 

(Data at this moment in the database table):

 

 

 

 

 

(Results of the):

 

 

 

If you request for the first time , there must be no data in the cache, so you need to ask the database for data;

 

Second request:

 

(Change the data of the corresponding table in the database before requesting)

 

 

 

(Results of the):

 

 

 

For the second request , since there is no absolute expiration time of the cache item, there is still data in the cache, so you don't need to ask the database for data, just get it from the cache;

 

Request after 30s:

 

(Data at this moment in the database table):

 

 

 

(Results of the):

 

 

 

The data in the cache has expired and has been removed, and you need to re-request to the database;

 

As can be seen from the above three requests, the cache data update is indeed achieved in the end.

 

But it can also be seen that this has a disadvantage: during the period of time before the expiration time, the requested data is still the original data in the cache, which is inconsistent with the data in the database.

 

The absolute expiration time point set should be set according to the tolerability of the actual data refresh, and it happens that the tolerability in my application scenario is the most unpredictable. It requires that when the data in the database changes after , the corresponding data in the cache must be changed immediately after the next request. Of course, you can also adjust the expiration time as small as possible to one second. Of course, in this case, we still have to make frequent requests to the database. Isn't that deviating from our original purpose of using cache optimization?

 

So now the question is: Is there a way to establish a connection between the database and the server program, this connection is like a kind of "telepathy", when the data in the database table changes, the server can be immediately The corresponding cache item in "sensing" this change, thus invalidating the original cache item? The answer is, of course, yes.

 

Database dependent cache

 

ASP.NET has 3 types of dependencies:

 

  • Cache project dependencies

     

  • file or folder dependencies

     

  • database dependency

 

This article is about database dependencies: Database cache dependencies are a technique for automatically invalidating cached data objects when the relevant data in the database is modified.

 

When I didn't know there was a database dependency before, I thought about using file or folder dependencies to implement a function similar to database dependency caching. The general idea is: use a certain file as a medium, after making data changes to the database table , and modify the file to trigger cache invalidation.

 

Fortunately, after reading the blog posts written by the great gods, I immediately stopped my "stupid" thinking. Doing that is actually superfluous, and it can't be implemented very well. There is no need for ready-made database dependencies.

 

Let's see how to use it:

 

1. Configuration:

 

1) Add to the Web.config file under the mvc project of the current website

 

<!--(database connection string) <configuration> node configuration -->

 

<connectionStrings>

   <add name="connStr" connectionString="server=127.0.0.1; user id=sa; password=root; database=LZXF" providerName="System.Data.SqlClient" />

</connectionStrings>

 

 <!-- (cache database dependency configuration) <system.web> node configuration -->

    <caching>

      <sqlCacheDependency enabled="true">

        <databases>

          <add name="LZXF" pollTime="5000" connectionStringName="connStr" />

        </databases>

      </sqlCacheDependency>

    </caching>    

 

2) Add in Application_Start()

 

//Configure cache database dependencies

string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["connStr"].ToString();

//Start the data cache dependency function of the database      

SqlCacheDependencyAdmin.EnableNotifications(connectionString);

//Enable data table cache  

SqlCacheDependencyAdmin.EnableTableForNotifications(connectionString, "(table name)"); //The second parameter can be a single table name or an array of table names

 

2. Code part

 

public ActionResult GetAllFJs()

{

    // try to fetch data from cache

    var FJIdNames = HttpContext.Cache["FJIdNames"];

    if (null == FJIdNames) //There is no data in the cache

    {

        //Query data from database

        FJIdNames = FJService.GetAll().Select(fj => new { Id = fj.Id, Name = fj.Name }).ToArray();

        //Cache the data for the next use (use the database-dependent cache, when the data of the corresponding table in the database changes, the cache is invalid)

        HttpContext.Cache.Insert("FJIdNames", FJIdNames, new SqlCacheDependency("LZXF", "T_FJs"));

    }

    //Convert the obtained data into a json format string

    string jsonResult = CommonHelper.ConvertToJsonStr(FJIdNames);

    //result string returned to the browser

    return Content(jsonResult);

}

 

Among them, SqlCacheDependency (database cache dependency class) is the most important class, that is, it establishes a "communication bridge" between the database and the server program.

 

Use one of its constructors:

 

public SqlCacheDependency(string databaseEntryName, string tableName)  to create a database cache dependency class object and pass it to the method Insert that creates a cache item, so as to establish the database dependency of the cache item, which will be destroyed whenever the data in the specified table changes. the cache entry.

 

Take a look at the execution result:

 

 

Before changing the database table data:

 

 

(Results of the):

 

 

 

After changing database table data:

 

 

 

(Results of the):

 

 

 

After changing the data in the database table, request the data and request the latest data, indicating that the old cache has been removed

 

Since it will be used, the next thing to look at is the principle, (the principle, the principle is the most important)

 

After using it, you will be very confused, how is it achieved?

 

Thinking: The first is to change the data in the database table, this step must lead to some kind of operation. Changing data in a table in the database triggers an action? Isn't it about triggers?

 

Let's take a look at what's more in the database:

 

Open sqlServerManagement to view database discovery

 

 

 

There is one more AspNet_SqlCacheTablesForChangeNotification table, the contents of the table:

 

 

 

The trigger to look for is here:

 

 

 

Take a look at what's inside the trigger:

 

 

 

That is to say: when the operations of INSERT, UPDATE, DELETE occur in the T_FJs table, the stored procedure dbo.AspNet_SqlCacheUpdateChangeIdStoredProcedure is executed. This stored procedure is automatically generated when we enable the cache dependency of sql server.

 

Find the stored procedure dbo.AspNet_SqlCacheUpdateChangeIdStoredProcedure, here:

 

 

 

The content is:

 

 

 

Summarize:

 

When sqlserver enables cache dependencies, it will add corresponding tables, triggers and some stored procedures to the corresponding database. It uses triggers to monitor changes in table data. If there are additions, deletions, or changes, insert data into the notification table, and then notify the website that subscribes to the notification that the cache item is invalid.

 

The last thing to say is that the use of cache dependencies is also limited: applications must be developed with ASP.Net and SQL Server, that is, SqlCacheDependency is based on Microsoft's system.

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324889877&siteId=291194637