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
Before we see how to update the comic books controller to handle deletes, let's review my solution for implementing the `ValidateComicBook` method.
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.6 -b handling-deletes
Before we see how to update the Comic
Books Controller to handle deletes,
0:00
let's review my solution for
implementing the ValidateComicBook method.
0:04
To review, the ValidateComicBook method,
which is called from both the add and
0:08
edit post action methods,
needs to be updated with a query
0:13
that checks if the provided issue
number is already in use or not.
0:17
To do that, we need to write a query
that checks if the database contains
0:21
a different Comic Book that is
associated with the same Series, and
0:26
has the same Issue Number.
0:30
Whenever I need to check for
the existence of a record or
0:32
entity in the database without
actually returning the entity,
0:35
itself, I typically use
the Any link operator,
0:38
which will return true if an entity is
found that matches our provided criteria.
0:42
For the predicate, I'm looking for
a comic book whose ID property value
0:46
doesn't equal the Passed In
comic book;s ID property value.
0:51
But whose Series ID and
0:55
Issue Number properties are equal to the
Passed In Comic Book's property values.
0:56
This query will return true if a comic
book other than the Passed In comic book
1:01
is found that it's associated with the
same series and has the same issue number.
1:06
Let's test the validation method and
see if it behaves as expected.
1:11
Let's try adding another Comic Book for
1:15
the Series,
Bone with an Issue Number of four.
1:18
And select Jeff Smith for
the Artist and Script for the Role.
1:25
Click the Save button and
we get an error message.
1:31
The provided Issue Number has already
been entered for the selected Series.
1:36
Okay, so far, so good.
1:41
Let's change the Issue Number to five and
try saving again.
1:43
And this time,
the Comic Book was successfully added.
1:47
Now, let's make sure that we
can edit the Comic Book without
1:51
getting a false positive or
an existing Issue Number.
1:53
Set an Average Rating value and
click the Save button.
1:59
And here's our updated Comic Book.
2:03
Great, now, we have Comic Book Creates and
2:06
Updates, including the server side
validation fully implemented.
2:08
Now, let's turn our attention to
implementing the letter d in crud deletes.
2:13
There are two action methods
that we need to update.
2:18
The Delete Get action method And
2:21
the Delete Post action method.
2:26
The Delete Get action methods only parameter is a nullable
2:33
integer-named id like the detail and
adequate action methods.
2:37
If the id parameter is null,
2:41
we immediately return
a BadRequest HttpStatusCode.
2:43
Otherwise, we attempt to
retrieve the comicBook from
2:49
the database with the related
Series eagerly loaded.
2:52
And we return a NotFound HTTP Status Code
if we don't find a comicBook.
2:56
Then, we call the View method,
passing in the comicBook instance.
3:02
The query to retrieve the comic book
can use the link, Where operator
3:06
in order to retrieve the comicBook
with a Passed In ID parameter value,
3:10
followed by a call to the SingleOrDefault
method to execute the query.
3:14
Don't forget the call to the Include
operator in order to eagerly load
3:18
the related Series.
3:23
_context.ComicBooks.Include(cb =>
3:24
cb.Series).Where(cb =>
3:32
cb.Id == id).SingleOrDefault().
3:38
The Delete Post action method
is pretty straight forward.
3:47
It accepts an id parameter value which
is used to delete the comicBook.
3:50
Then, we set the message key
in the TempData dictionary and
3:54
re-direct the user to the Index action,
which is our web apps home page.
3:58
To delete the comic
book from the database,
4:03
we can create a comic book entity using
the id parameter value that we're passed.
4:05
Attach it to the context
using the entry method.
4:11
And set its entry state to deleted.
4:14
And call the context's save changes method
in order to perform the deletion in
4:18
the database.
4:23
var comicBook = new ComicBook().
4:24
And set { Id = id};.
4:30
Then, _context.Entry (comicBook).State
4:33
= EntityState.Deleted.
4:40
And finally, _context.SaveChanges();.
4:44
Let's test our changes To
delete a comic book, you
4:50
first need to view the Comic Book Detail
page of the comic book you want to delete.
4:57
I'll click the Detail button on
Issue Number five of the Bone Series.
5:03
Then, on the Comic Book Detail page,
click the Delete button.
5:07
We're presented with Delete Comic Book
page to confirm the deletion.
5:12
You can click the Cancel button to return
to the Detail page, but I'll go ahead and
5:16
click the Delete button
to delete the comic book.
5:20
We're then redirected
to the Comic Books page
5:24
which displays a message confirming
the comic book deletion.
5:27
We can also see that Issue Number
5 of the Bone Series
5:31
is no longer in the list of Comic Books.
5:34
With those changes completed, we can now
create, update, and delete comic books.
5:37
Nice work making progress on our web app.
5:42
It's worth noting that our approach for deleting a comic book
5:45
relies upon cascade deletes to delete
the related comic book artist records.
5:48
This works fine for comic books, but
for artists or series, we may not want
5:52
users to be able to delete a large
number of related comic book records.
5:57
Let's look at a couple of alternative
strategies for handling deletes.
6:02
One option would be to retrieve and
display related data
6:05
on the detail page for a record
that the user is trying to delete.
6:09
For instance, under Artist Detail page,
6:12
we would display all of the comic books
that the artist is associated with.
6:15
We could then disable the Delete button,
and
6:19
display a tool tip that lets the user know
that the artist must first be removed from
6:21
all of the listed comic books
before the artist can be deleted.
6:25
This is much more of
a conservative approach than just
6:29
letting the cascade deletes happen.
6:32
But while it prevents the deletion
of records that are in use,
6:34
it does give the user the information
that they need in order to move forward.
6:37
If they, in fact, need to actually delete
the record in question, another option
6:41
would be to allow the user to delete
the records, even if they are in use.
6:46
But instead of physically deleting
the record from the database,
6:50
we simply mark the record as deleted.
6:53
This is typically done by setting
an active property to the value of false.
6:55
These kinds of deletes
are known as Logical Deletes.
7:00
Allowing users to perform Logical Deletes
7:03
give developers a way to grant
users more power in the application
7:06
while still retaining some
level of control over the data.
7:10
For example, a user might delete a record,
7:13
only to realize later that
they shouldn't have done that.
7:16
To undo the deletion,
they could contact an administrator or
7:20
superuser do it in turn.
7:24
Use a special page to search for
and undeleted the deleted record.
7:26
By saving this active property
back to a value of true.
7:30
Logical Deletes seem too good to be true,
right?
7:32
Well, there are some draw
backs to be aware of.
7:37
If your web app requires users to
delete large numbers of records,
7:39
your database can grow
unexpectantly large,
7:43
as deleted records are never
actually removed from the database.
7:46
Another draw back is that most of
your queries will need to filter
7:50
out records who's active values are false.
7:54
Otherwise, list pages in the web app might
unintentionally contain deleted records.
7:57
None of these issues are insurmountable.
8:02
There are simply things you need
to consider when you're deciding
8:04
how you handle deletes in your web app.
8:07
Furthermore, you can even mix and
match approaches within the same app.
8:09
Critical record types
could use logical deletes,
8:14
while other record types
could use physical deletes.
8:17
Coming up next, we'll review
the Comic Book Artist Controller, and
8:20
give you a chance to finish
implementing it on your own.
8:24
You need to sign up for Treehouse in order to download course files.
Sign up