Caching Entities8:16 with James Churchill
Let's see how we can leverage an entity cache to reduce the number of Entity Framework queries that our app needs to run.
So far in this workshop, 0:00 we've been focusing on improving the performance of EF queries in order to 0:01 improve the overall performance of retrieving entities from the database. 0:05 But we can go one step further by not running a query at all. 0:09 Well, you need to run at least one query 0:14 to initially retrieve the entities from the database. 0:16 But subsequent queries to retrieve the same entities can be avoided 0:19 by using an entity cache. 0:22 [SOUND] Some list of entities are needed again and again. 0:25 For example, in the comic book library manager web app we need a list of 0:29 the available series every time that a comic book is added or updated. 0:33 Now imagine that we had [SOUND] hundreds or 0:38 maybe even thousands of users every day, adding and updating comic books. 0:41 Even if the query to retrieve the series entities was relatively inexpensive, 0:46 a query that is ran thousands [SOUND] tens of thousands of times per day can amount 0:51 to a significant amount of system resources. 0:55 By utilizing a cache, it's possible to dramatically reduce the system resources 0:58 required, for retrieving the list of series entities. 1:03 When the list of series is initially retrieved, 1:07 we store away a copy of entities in the cache. 1:09 The next time that the list of series is needed, 1:12 we first check our cache to see if it contains the list of series entities. 1:14 And if it does, we return that list of entities instead of retrieving the data 1:18 from the database and materializing a new list of entities. 1:22 Utilizing a cache is not always possible. 1:27 If data changes frequently, then storing that data in a cache would mean that it 1:30 would grow stale too quickly for it to be useful. 1:34 Luckily, the list of series is relatively static as series entities are not added, 1:37 updated or deleted very often. 1:42 This makes series entities a good candidate for caching. 1:44 The .NET Framework makes it easy to create a cache for our web apps entities. 1:48 Let's see how. 1:52 All of our web apps did access code is located in the shared class library. 1:54 So, let's put the class for our cache there as well. 1:59 Add a class named Entity cache to the data folder. 2:03 Our cache will internally utilize the .NET Framework's memory cache class. 2:08 A type that implements an in-memory cache. 2:13 To get access to that type, we need to add a reference to its containing assembly, 2:16 system.runtime.caching. 2:21 Right click on the References folder and select Add Reference. 2:23 On the left-hand side of the reference manager dialogue, 2:27 select Assemblies and then Framework. 2:31 Then scroll down to System.Runtime.Caching. 2:34 Check the box to the left, and click OK. 2:42 Then add a using directive for the System.Runtime.Caching namespace. 2:48 Now, we're ready to implement our class. 2:54 To start, let's set up the internal cache that our class will utilize. 2:58 To do that, we can use the MemoryCache class's default property to get 3:02 a reference to the default instance of an in memory cache for our application. 3:06 Using a private field to store the reference to the MemoryCache default 3:13 instance keeps our cache implementation hidden from the rest of our application. 3:17 We're effectively wrapping or 3:23 encapsulating the MemoryCache class within our own class. 3:25 This gives us the ability to change our implementation in the future 3:29 without affecting any of the consumers of our entity cache class. 3:33 We want a singular entity cache to be used across our entire application, so 3:38 that every time that a list of series is needed, 3:43 the same entity cache will be used to provide that list of entities. 3:46 One way to accomplish that is to make the _cache private field static. 3:50 Adding the static key word to the field associates the field 3:57 with the class itself. 4:00 We can go a step further and make the entity class itself static. 4:02 Making a class static ensures that consumers of that class can't instantiate 4:09 it, that will also force us to make all of its methods static, 4:14 which will work fine for our purposes. 4:17 The first method that we'll add to our class is a static method to add an item to 4:20 the cache. 4:24 Each item that is added to the cache is associated with a key. 4:28 That gives you an easy way to retrieve that item from the cache later on. 4:32 Let's add two parameters to our add method: one for the item key and 4:37 another for the item itself to add to the cache. 4:41 The key parameter is any string value and the item can be any object. 4:46 To add an item to the cache we call the add method on the memory cache object, 4:52 supply in the key value and a fixed date and 4:58 time at which the cache entry will expire. 5:02 The cache entry expiration needs to be provided as a daytime offset value. 5:06 One way to accomplish that is to use the daytime offset's now static property 5:11 to get a value for the current date and 5:16 time, and call the add minutes method to add an arbitrary number of minutes. 5:18 Let's add 60 minutes so the cache entry will expire in an hour. 5:24 Instead of hard-coding the minutes to use here in this method call, 5:28 let's add a parameter with a default value, so 5:31 the caller can optionally specify the number of minutes. 5:34 Now, let's add a static method to get an item from the cache. 5:44 Remember when we added an item to the cache we provided a key value for 5:53 that item. 5:57 So to get an item from the cache, we need to supply the key for that item. 5:58 Given that, let's add a parameter for the key. 6:02 Before we attempt to retrieve an item from the cache, we can use the contains method 6:08 to check if the cache contains an item or a provided key value. 6:12 And if the Contains method returns true, we can then safely call the cache's Get 6:24 method to retrieve the item from the cache. 6:28 And if the Contains method returns false, we can simply return null. 6:42 The caller of our Get method likely knows the type of 6:49 object that they're attempting to retrieve from the cache. 6:52 Given that we can make our method a generic method 6:55 which will allow us to explicitly cast the object returned 6:58 from the cache's get method to the generic type parameters type. 7:02 Since our generic type t can be any valid .NET type including value types 7:07 like int or double, null isn't always a valid return value. 7:12 We can replace null with a default keyword, 7:17 which will return the default value for the specified generic type. 7:20 Let's also add a method to remove an item from the cache. 7:25 Having a method to remove an item from the cache is helpful because the consumer of 7:28 the cache is often able to determine when a cached item has grown stale. 7:32 We'll see an example of that in the next video. 7:38 Before we attempt to remove an item from the cache, 7:41 we wanna make sure that the cache contains an item for the provided key. 7:44 And if the Contains method returns true then we know it's safe to call the cache's 7:57 remove method, That completes our entity cache class. 8:01 Next we can update the series repository to make use of it. 8:11
You need to sign up for Treehouse in order to download course files.Sign up