Recently, I wrote about a way that you can use one route to direct traffic to different controllers and actions in ASP.NET Core MVC.
In that example, I mentioned that there were six different types of pages that would be handled by one route.
This is great, but the problem I experienced was the data for each different types of page was housed in six different database tables.
I couldn't just potentially call up to six different database queries to try and match the type of page against the URL being pulled in. The website performance would have been compared to the speed of a slug.
Of course I could have done some funky UNION join against all six tables, but that would have still of meant a call to the database.
The idea I came up with is using a singleton within dependency injection.
For anyone that doesn't know what a singleton is, it's a class that keeps it's properties and variables set for the lifetime of the application.
So when running a website application, the singleton will be created when the website application starts, and the singleton will be destroyed once the website application stops. Each thread to the website application would be able to access the same values for each of the properties from the singleton.
The singleton would call the database to get a list of all the potential URL's on creation and when one of the types of pages is updated. This would be locked down using the "lock" keyword so no other threads can access the function whilst it's doing it's job.
The advantages of this is that the database is only involved when the website application starts, or a change has been made to one of the types of pages.
The singleton class would store a list of all the URL's and which controller and action each URL would go to. These would be stored in a ConcurrentDictionary class (rather than the Dictionary class) to support multiple users accessing it at the same time. This dictionary is effectively "the cache".
The "key" property of the ConcurrentDictionary would be the URL hashed into a number (the GetHashedCode function that appears on all objects). I did this to speed up the lookup of the URL.
As an addition, when a user updates one of the types of pages, it fires a new thread to update the URL's. This means that the user who has updated the page doesn't have to hang around for the background service to complete it's job in updating the URL's.
An example on how to do this is below: