Bummer! This is just a preview. You need to be signed in with a Basic account to view the entire video.
Start a free Basic trial
to watch this video
Now that we have EF configured, we're ready to update our first controller to read data from the database. But before we do that, let's talk about the lifetime of our database context object instances.
Follow Along
To follow along committing your changes to this course, you'll need to fork the dotnet-comic-book-library-manager repo. Then you can clone, commit, and push your changes to your fork like this:
git clone <your-fork>
cd dotnet-comic-book-library-manager
git checkout tags/v2.3 -b handling-reads
Keyboard Shortcuts
-
CTRL+PERIOD
orCTRL+DOT
- Quick Actions -
CTRL+MINUS
- Navigate Back -
CTRL+SHIFT+B
- Build Solution
-
0:00
Now that we have EF configured,
-
0:02
we're ready to update our first controller to read data from the database.
-
0:06
But before we do that,
-
0:07
let's talk about the lifetime of our database context object instances.
-
0:12
A context object's lifetime, for the sake of our discussion,
-
0:15
is the time from when it's instantiated to when it's disposed.
-
0:19
We don't want to instantiate a context every time that we need to retrieve or
-
0:23
persist data.
-
0:25
But we also don't want a context that lives for too long.
-
0:28
A long living context can,
-
0:29
over time, end up consuming more system memory than we would want.
-
0:34
And have a negative impact on the performance of our application.
-
0:37
So, what are our options?
-
0:40
Let's review how MVC handles requests.
-
0:42
The process begins with a user entering a URL into a browser's address bar,
-
0:47
which causes an HTTP request to be sent to the server.
-
0:50
The server receives the request and hands it off to the MVC Framework.
-
0:55
When processing the request,
-
0:57
MVC uses simple pattern matching against the URL path.
-
1:00
To determine the name of the controller and the action that should be used
-
1:04
to handle the request in the form of controller / action.
-
1:09
So the path ComicBooks / Index
-
1:12
would map to a controller named ComicBooks and an action method named Index.
-
1:17
This process is known as URL routing.
-
1:20
Once the controller and action method have been identified,
-
1:23
MVC then instantiates an instance of the controller class.
-
1:27
And calls the appropriate action method on that instance.
-
1:30
The action method returns an action result which in turn is rendered and
-
1:35
sent back to the user's browser as an HTTP response.
-
1:39
[SOUND] This process is repeated for each request.
-
1:43
Given that, each request is associated with its own instance of the appropriate
-
1:47
controller class.
-
1:49
Aligning the lifetime of our context with the controller's lifetime,
-
1:53
gives us a convenient way of managing the lifetime of the context.
-
1:57
Adding a default constructor to the Comic Book's controller class will allow us to
-
2:01
instantiate an instance to the context when the controller is instantiated.
-
2:06
That takes care of how to manage the start of the context's lifetime.
-
2:10
In the next video, we'll see how we can manage the end of the context's lifetime,
-
2:14
by disposing our context when the controller is disposed.
-
2:18
Let's jump back into the Comic Book's controller, and
-
2:21
make our first set of changes.
-
2:23
We need a private field to hold a reference to the context object instance.
-
2:27
Private Context, then press Ctrl period or
-
2:31
dot to add the using directive for the ComicBookShared.Data name space.
-
2:38
We'll start the private field name with an underscore, so
-
2:41
that it's easy to identify throughout our code.
-
2:43
_context, and initialize the field to null,
-
2:49
and a public default constructor
-
2:59
And initialize the private field to an instance at the context class.
-
3:03
Now that we have our context's instance, let's add our first query.
-
3:07
Starting with the index action method, we need a query that returns
-
3:11
a list of comic books with the related series, entities eagerly loaded.
-
3:16
We can grab the query that we need from the repository class GetComicBooks method.
-
3:21
Select the code for the query starting with the DB set property, and
-
3:25
copy to the clipboard.
-
3:27
Then in the index action method,
-
3:30
replace the comic books collection initialization with the reference
-
3:33
to the context private field followed by the contents in the clipboard.
-
3:38
Moving on to the detail action method, we need a query that returns a single comic
-
3:43
book with the related series and artist entities eagerly loaded.
-
3:47
Again, we can grab the query that we need from the repository class,
-
3:51
this time from the GetComicBook method.
-
3:55
Select the query and copy to the clipboard.
-
3:57
Then, in the detail action method, replace the comic book object initialization
-
4:02
with the reference to the context private field,
-
4:05
followed by the contents of the clipboard.
-
4:07
And change the comic book ID variable to just ID.
-
4:17
Which is the name of the parameter being passed to the action method.
-
4:21
And now the add get action method.
-
4:30
In this action method, we need to pass the context into the viewModel's Init method,
-
4:35
and that's easy to do.
-
4:37
Almost just as soon as we finish typing _context,
-
4:41
Visual Studio will let us know that we have a compilation error.
-
4:44
Now, we need to update the method definition
-
4:47
to accept an instance of the context class.
-
4:50
I'll put my cursor on the method name and
-
4:52
press F12 to browse to the method definition.
-
4:55
Add a parameter of type Context named context, and now we get a new error.
-
5:01
ComicBooksAddViewModel.Init context no suitable method found to override.
-
5:07
The viewModel class inherits from the ComicBooksBaseViewModel class, and
-
5:12
overrides its Init method.
-
5:14
When overriding a method in the base class,
-
5:16
the method signature needs to match the method that you're overriding.
-
5:20
To resolve this error, we need to update the Init method in the base class
-
5:25
to have the same signature as the Init method in the descendant class.
-
5:29
Browse through the base class method,
-
5:31
by placing the cursor on the call to that method, and pressing F12.
-
5:36
And add a parameter of type Context.
-
5:41
Named context.
-
5:43
While we're here, let's replace this new list of series entities
-
5:47
with a query to get the list of series from the context.
-
5:50
context.Series.OrderBy(s =>
-
5:56
s.Title).ToList(),.
-
6:02
We can browse back the ComicBooksAddViewModel class by
-
6:06
pressing Ctrl minus twice.
-
6:08
Now we're getting an error with our call to the base class Init method.
-
6:12
There is no argument given that corresponds to the required formal
-
6:16
parameter context of ComicBooksBaseViewModel.Init(Context).
-
6:21
We need to pass the Context parameter to the Init method call.
-
6:25
And we can replace the new list of artists and
-
6:28
roles entities with queries to get those respective lists.
-
6:31
Context.Artists.OrderBy(a =>
-
6:38
a.Name).ToList(), and for roles.
-
6:49
Context.Roles.OrderBy(r =>
-
6:54
r.Name).ToList(),.
-
6:58
Let's press Ctrl+Shift+B to build our project and check the state of things.
-
7:06
We got three compilation errors,
-
7:08
each with the same description that we saw just a bit ago.
-
7:12
Looks like there are some additional calls to the viewModel.Init
-
7:15
method that we need to update.
-
7:16
Double-click the first error in the list to jump to that line of code, and
-
7:20
update the method to pass the _context private field.
-
7:24
And repeat twice more.
-
7:37
Now that our project is building,
-
7:39
let's test our changes to ensure that the database initializer works as expected.
-
7:44
I'll open the SQL Server Object Explorer window and
-
7:47
delete the ComicBookLibraryManager database.
-
7:54
Then, I'll run the app.
-
8:01
And after a bit of a delay while EF is busy recreating our database,
-
8:05
our list of comic books displays.
-
8:10
Clicking on a Detail button takes us to that comic book's detail page.
-
8:15
Click the Back button to return to the comic books list page,
-
8:18
then click the Add Comic Book button.
-
8:22
And here's the Add Comic Book page with the series.
-
8:29
Artist, and Role select list, populated with their respective available values.
-
8:38
By instantiating an instance of the context class,
-
8:40
in the ComicBooksController class constructor, we've aligned the beginning
-
8:44
of our context's lifetime with the beginning of the controller's lifetime.
-
8:48
But we still need to align the end of the context's lifetime
-
8:51
to the end of the controller's lifetime.
-
8:53
But how do we do that?
-
8:55
How can we dispose our context object instance when the controller is disposed?
You need to sign up for Treehouse in order to download course files.
Sign up