This workshop will be retired on May 1, 2025.
Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Preview
Start a free Courses trial
to watch this video
Let's see how we can leverage an entity cache to reduce the number of Entity Framework queries that our app needs to run.
Additional Learning
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
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 upYou need to sign up for Treehouse in order to set up Workspace
Sign up