1 00:00:00,360 --> 00:00:01,750 So far in this workshop, 2 00:00:01,750 --> 00:00:05,380 we've been focusing on improving the performance of EF queries in order to 3 00:00:05,380 --> 00:00:09,390 improve the overall performance of retrieving entities from the database. 4 00:00:09,390 --> 00:00:14,040 But we can go one step further by not running a query at all. 5 00:00:14,040 --> 00:00:16,640 Well, you need to run at least one query 6 00:00:16,640 --> 00:00:19,318 to initially retrieve the entities from the database. 7 00:00:19,318 --> 00:00:22,990 But subsequent queries to retrieve the same entities can be avoided 8 00:00:22,990 --> 00:00:24,760 by using an entity cache. 9 00:00:25,960 --> 00:00:29,393 [SOUND] Some list of entities are needed again and again. 10 00:00:29,393 --> 00:00:33,526 For example, in the comic book library manager web app we need a list of 11 00:00:33,526 --> 00:00:38,460 the available series every time that a comic book is added or updated. 12 00:00:38,460 --> 00:00:41,219 Now imagine that we had [SOUND] hundreds or 13 00:00:41,219 --> 00:00:46,425 maybe even thousands of users every day, adding and updating comic books. 14 00:00:46,425 --> 00:00:51,147 Even if the query to retrieve the series entities was relatively inexpensive, 15 00:00:51,147 --> 00:00:55,797 a query that is ran thousands [SOUND] tens of thousands of times per day can amount 16 00:00:55,797 --> 00:00:58,568 to a significant amount of system resources. 17 00:00:58,568 --> 00:01:03,175 By utilizing a cache, it's possible to dramatically reduce the system resources 18 00:01:03,175 --> 00:01:07,270 required, for retrieving the list of series entities. 19 00:01:07,270 --> 00:01:09,730 When the list of series is initially retrieved, 20 00:01:09,730 --> 00:01:12,010 we store away a copy of entities in the cache. 21 00:01:12,010 --> 00:01:14,800 The next time that the list of series is needed, 22 00:01:14,800 --> 00:01:18,660 we first check our cache to see if it contains the list of series entities. 23 00:01:18,660 --> 00:01:22,960 And if it does, we return that list of entities instead of retrieving the data 24 00:01:22,960 --> 00:01:26,280 from the database and materializing a new list of entities. 25 00:01:27,620 --> 00:01:30,300 Utilizing a cache is not always possible. 26 00:01:30,300 --> 00:01:34,190 If data changes frequently, then storing that data in a cache would mean that it 27 00:01:34,190 --> 00:01:37,430 would grow stale too quickly for it to be useful. 28 00:01:37,430 --> 00:01:42,510 Luckily, the list of series is relatively static as series entities are not added, 29 00:01:42,510 --> 00:01:44,800 updated or deleted very often. 30 00:01:44,800 --> 00:01:47,510 This makes series entities a good candidate for caching. 31 00:01:48,510 --> 00:01:52,610 The .NET Framework makes it easy to create a cache for our web apps entities. 32 00:01:52,610 --> 00:01:53,230 Let's see how. 33 00:01:54,700 --> 00:01:59,220 All of our web apps did access code is located in the shared class library. 34 00:01:59,220 --> 00:02:03,250 So, let's put the class for our cache there as well. 35 00:02:03,250 --> 00:02:06,680 Add a class named Entity cache to the data folder. 36 00:02:08,280 --> 00:02:13,290 Our cache will internally utilize the .NET Framework's memory cache class. 37 00:02:13,290 --> 00:02:16,580 A type that implements an in-memory cache. 38 00:02:16,580 --> 00:02:21,650 To get access to that type, we need to add a reference to its containing assembly, 39 00:02:21,650 --> 00:02:23,571 system.runtime.caching. 40 00:02:23,571 --> 00:02:27,156 Right click on the References folder and select Add Reference. 41 00:02:27,156 --> 00:02:31,000 On the left-hand side of the reference manager dialogue, 42 00:02:31,000 --> 00:02:34,720 select Assemblies and then Framework. 43 00:02:34,720 --> 00:02:37,965 Then scroll down to System.Runtime.Caching. 44 00:02:42,940 --> 00:02:46,080 Check the box to the left, and click OK. 45 00:02:48,560 --> 00:02:54,420 Then add a using directive for the System.Runtime.Caching namespace. 46 00:02:54,420 --> 00:02:56,580 Now, we're ready to implement our class. 47 00:02:58,360 --> 00:03:02,630 To start, let's set up the internal cache that our class will utilize. 48 00:03:02,630 --> 00:03:06,857 To do that, we can use the MemoryCache class's default property to get 49 00:03:06,857 --> 00:03:11,513 a reference to the default instance of an in memory cache for our application. 50 00:03:13,891 --> 00:03:17,763 Using a private field to store the reference to the MemoryCache default 51 00:03:17,763 --> 00:03:23,070 instance keeps our cache implementation hidden from the rest of our application. 52 00:03:23,070 --> 00:03:25,120 We're effectively wrapping or 53 00:03:25,120 --> 00:03:29,780 encapsulating the MemoryCache class within our own class. 54 00:03:29,780 --> 00:03:33,440 This gives us the ability to change our implementation in the future 55 00:03:33,440 --> 00:03:37,430 without affecting any of the consumers of our entity cache class. 56 00:03:38,590 --> 00:03:43,600 We want a singular entity cache to be used across our entire application, so 57 00:03:43,600 --> 00:03:46,230 that every time that a list of series is needed, 58 00:03:46,230 --> 00:03:50,720 the same entity cache will be used to provide that list of entities. 59 00:03:50,720 --> 00:03:55,800 One way to accomplish that is to make the _cache private field static. 60 00:03:57,090 --> 00:04:00,600 Adding the static key word to the field associates the field 61 00:04:00,600 --> 00:04:02,560 with the class itself. 62 00:04:02,560 --> 00:04:06,552 We can go a step further and make the entity class itself static. 63 00:04:09,694 --> 00:04:14,086 Making a class static ensures that consumers of that class can't instantiate 64 00:04:14,086 --> 00:04:17,544 it, that will also force us to make all of its methods static, 65 00:04:17,544 --> 00:04:20,290 which will work fine for our purposes. 66 00:04:20,290 --> 00:04:24,172 The first method that we'll add to our class is a static method to add an item to 67 00:04:24,172 --> 00:04:24,789 the cache. 68 00:04:28,674 --> 00:04:32,990 Each item that is added to the cache is associated with a key. 69 00:04:32,990 --> 00:04:37,150 That gives you an easy way to retrieve that item from the cache later on. 70 00:04:37,150 --> 00:04:41,430 Let's add two parameters to our add method: one for the item key and 71 00:04:41,430 --> 00:04:44,010 another for the item itself to add to the cache. 72 00:04:46,180 --> 00:04:52,690 The key parameter is any string value and the item can be any object. 73 00:04:52,690 --> 00:04:58,220 To add an item to the cache we call the add method on the memory cache object, 74 00:04:58,220 --> 00:05:02,060 supply in the key value and a fixed date and 75 00:05:02,060 --> 00:05:04,820 time at which the cache entry will expire. 76 00:05:06,000 --> 00:05:11,590 The cache entry expiration needs to be provided as a daytime offset value. 77 00:05:11,590 --> 00:05:16,620 One way to accomplish that is to use the daytime offset's now static property 78 00:05:16,620 --> 00:05:18,280 to get a value for the current date and 79 00:05:18,280 --> 00:05:23,320 time, and call the add minutes method to add an arbitrary number of minutes. 80 00:05:24,440 --> 00:05:28,048 Let's add 60 minutes so the cache entry will expire in an hour. 81 00:05:28,048 --> 00:05:31,934 Instead of hard-coding the minutes to use here in this method call, 82 00:05:31,934 --> 00:05:34,614 let's add a parameter with a default value, so 83 00:05:34,614 --> 00:05:37,903 the caller can optionally specify the number of minutes. 84 00:05:44,223 --> 00:05:47,789 Now, let's add a static method to get an item from the cache. 85 00:05:53,100 --> 00:05:57,200 Remember when we added an item to the cache we provided a key value for 86 00:05:57,200 --> 00:05:58,090 that item. 87 00:05:58,090 --> 00:06:02,660 So to get an item from the cache, we need to supply the key for that item. 88 00:06:02,660 --> 00:06:05,004 Given that, let's add a parameter for the key. 89 00:06:08,125 --> 00:06:12,686 Before we attempt to retrieve an item from the cache, we can use the contains method 90 00:06:12,686 --> 00:06:16,095 to check if the cache contains an item or a provided key value. 91 00:06:24,030 --> 00:06:28,701 And if the Contains method returns true, we can then safely call the cache's Get 92 00:06:28,701 --> 00:06:31,253 method to retrieve the item from the cache. 93 00:06:42,269 --> 00:06:46,370 And if the Contains method returns false, we can simply return null. 94 00:06:49,170 --> 00:06:52,140 The caller of our Get method likely knows the type of 95 00:06:52,140 --> 00:06:55,445 object that they're attempting to retrieve from the cache. 96 00:06:55,445 --> 00:06:58,765 Given that we can make our method a generic method 97 00:06:58,765 --> 00:07:02,445 which will allow us to explicitly cast the object returned 98 00:07:02,445 --> 00:07:06,035 from the cache's get method to the generic type parameters type. 99 00:07:07,215 --> 00:07:12,195 Since our generic type t can be any valid .NET type including value types 100 00:07:12,195 --> 00:07:17,230 like int or double, null isn't always a valid return value. 101 00:07:17,230 --> 00:07:20,390 We can replace null with a default keyword, 102 00:07:20,390 --> 00:07:23,610 which will return the default value for the specified generic type. 103 00:07:25,310 --> 00:07:28,800 Let's also add a method to remove an item from the cache. 104 00:07:28,800 --> 00:07:32,730 Having a method to remove an item from the cache is helpful because the consumer of 105 00:07:32,730 --> 00:07:38,180 the cache is often able to determine when a cached item has grown stale. 106 00:07:38,180 --> 00:07:40,520 We'll see an example of that in the next video. 107 00:07:41,760 --> 00:07:44,297 Before we attempt to remove an item from the cache, 108 00:07:44,297 --> 00:07:47,838 we wanna make sure that the cache contains an item for the provided key. 109 00:07:57,363 --> 00:08:01,416 And if the Contains method returns true then we know it's safe to call the cache's 110 00:08:01,416 --> 00:08:11,400 remove method, That completes our entity cache class. 111 00:08:11,400 --> 00:08:14,980 Next we can update the series repository to make use of it.