1 00:00:00,410 --> 00:00:04,420 Before we see how to update the Comic Books Controller to handle deletes, 2 00:00:04,420 --> 00:00:07,857 let's review my solution for implementing the ValidateComicBook method. 3 00:00:08,990 --> 00:00:13,930 To review, the ValidateComicBook method, which is called from both the add and 4 00:00:13,930 --> 00:00:17,720 edit post action methods, needs to be updated with a query 5 00:00:17,720 --> 00:00:21,840 that checks if the provided issue number is already in use or not. 6 00:00:21,840 --> 00:00:26,000 To do that, we need to write a query that checks if the database contains 7 00:00:26,000 --> 00:00:30,610 a different Comic Book that is associated with the same Series, and 8 00:00:30,610 --> 00:00:32,120 has the same Issue Number. 9 00:00:32,120 --> 00:00:35,020 Whenever I need to check for the existence of a record or 10 00:00:35,020 --> 00:00:38,660 entity in the database without actually returning the entity, 11 00:00:38,660 --> 00:00:42,200 itself, I typically use the Any link operator, 12 00:00:42,200 --> 00:00:46,840 which will return true if an entity is found that matches our provided criteria. 13 00:00:46,840 --> 00:00:51,350 For the predicate, I'm looking for a comic book whose ID property value 14 00:00:51,350 --> 00:00:55,240 doesn't equal the Passed In comic book;s ID property value. 15 00:00:55,240 --> 00:00:56,597 But whose Series ID and 16 00:00:56,597 --> 00:01:01,900 Issue Number properties are equal to the Passed In Comic Book's property values. 17 00:01:01,900 --> 00:01:06,845 This query will return true if a comic book other than the Passed In comic book 18 00:01:06,845 --> 00:01:11,390 is found that it's associated with the same series and has the same issue number. 19 00:01:11,390 --> 00:01:15,690 Let's test the validation method and see if it behaves as expected. 20 00:01:15,690 --> 00:01:18,140 Let's try adding another Comic Book for 21 00:01:18,140 --> 00:01:22,670 the Series, Bone with an Issue Number of four. 22 00:01:25,410 --> 00:01:30,250 And select Jeff Smith for the Artist and Script for the Role. 23 00:01:31,810 --> 00:01:36,700 Click the Save button and we get an error message. 24 00:01:36,700 --> 00:01:41,090 The provided Issue Number has already been entered for the selected Series. 25 00:01:41,090 --> 00:01:43,280 Okay, so far, so good. 26 00:01:43,280 --> 00:01:46,390 Let's change the Issue Number to five and try saving again. 27 00:01:47,880 --> 00:01:51,110 And this time, the Comic Book was successfully added. 28 00:01:51,110 --> 00:01:53,900 Now, let's make sure that we can edit the Comic Book without 29 00:01:53,900 --> 00:01:56,660 getting a false positive or an existing Issue Number. 30 00:01:59,600 --> 00:02:02,230 Set an Average Rating value and click the Save button. 31 00:02:03,780 --> 00:02:06,310 And here's our updated Comic Book. 32 00:02:06,310 --> 00:02:08,980 Great, now, we have Comic Book Creates and 33 00:02:08,980 --> 00:02:13,700 Updates, including the server side validation fully implemented. 34 00:02:13,700 --> 00:02:18,540 Now, let's turn our attention to implementing the letter d in crud deletes. 35 00:02:18,540 --> 00:02:21,460 There are two action methods that we need to update. 36 00:02:21,460 --> 00:02:26,352 The Delete Get action method And 37 00:02:26,352 --> 00:02:29,160 the Delete Post action method. 38 00:02:33,935 --> 00:02:37,561 The Delete Get action methods only parameter is a nullable 39 00:02:37,561 --> 00:02:41,641 integer-named id like the detail and adequate action methods. 40 00:02:41,641 --> 00:02:43,734 If the id parameter is null, 41 00:02:43,734 --> 00:02:47,755 we immediately return a BadRequest HttpStatusCode. 42 00:02:49,701 --> 00:02:52,381 Otherwise, we attempt to retrieve the comicBook from 43 00:02:52,381 --> 00:02:55,070 the database with the related Series eagerly loaded. 44 00:02:56,520 --> 00:03:02,580 And we return a NotFound HTTP Status Code if we don't find a comicBook. 45 00:03:02,580 --> 00:03:06,940 Then, we call the View method, passing in the comicBook instance. 46 00:03:06,940 --> 00:03:10,320 The query to retrieve the comic book can use the link, Where operator 47 00:03:10,320 --> 00:03:14,520 in order to retrieve the comicBook with a Passed In ID parameter value, 48 00:03:14,520 --> 00:03:18,890 followed by a call to the SingleOrDefault method to execute the query. 49 00:03:18,890 --> 00:03:23,470 Don't forget the call to the Include operator in order to eagerly load 50 00:03:23,470 --> 00:03:24,874 the related Series. 51 00:03:24,874 --> 00:03:32,893 _context.ComicBooks.Include(cb => 52 00:03:32,893 --> 00:03:38,590 cb.Series).Where(cb => 53 00:03:38,590 --> 00:03:47,050 cb.Id == id).SingleOrDefault(). 54 00:03:47,050 --> 00:03:50,560 The Delete Post action method is pretty straight forward. 55 00:03:50,560 --> 00:03:54,890 It accepts an id parameter value which is used to delete the comicBook. 56 00:03:54,890 --> 00:03:58,215 Then, we set the message key in the TempData dictionary and 57 00:03:58,215 --> 00:04:03,140 re-direct the user to the Index action, which is our web apps home page. 58 00:04:03,140 --> 00:04:05,732 To delete the comic book from the database, 59 00:04:05,732 --> 00:04:11,070 we can create a comic book entity using the id parameter value that we're passed. 60 00:04:11,070 --> 00:04:14,370 Attach it to the context using the entry method. 61 00:04:14,370 --> 00:04:17,680 And set its entry state to deleted. 62 00:04:18,774 --> 00:04:23,301 And call the context's save changes method in order to perform the deletion in 63 00:04:23,301 --> 00:04:24,200 the database. 64 00:04:24,200 --> 00:04:30,461 var comicBook = new ComicBook(). 65 00:04:30,461 --> 00:04:33,580 And set { Id = id};. 66 00:04:33,580 --> 00:04:40,515 Then, _context.Entry (comicBook).State 67 00:04:40,515 --> 00:04:44,481 = EntityState.Deleted. 68 00:04:44,481 --> 00:04:50,890 And finally, _context.SaveChanges();. 69 00:04:50,890 --> 00:04:57,727 Let's test our changes To delete a comic book, you 70 00:04:57,727 --> 00:05:03,040 first need to view the Comic Book Detail page of the comic book you want to delete. 71 00:05:03,040 --> 00:05:07,130 I'll click the Detail button on Issue Number five of the Bone Series. 72 00:05:07,130 --> 00:05:10,660 Then, on the Comic Book Detail page, click the Delete button. 73 00:05:12,080 --> 00:05:16,450 We're presented with Delete Comic Book page to confirm the deletion. 74 00:05:16,450 --> 00:05:20,740 You can click the Cancel button to return to the Detail page, but I'll go ahead and 75 00:05:20,740 --> 00:05:22,860 click the Delete button to delete the comic book. 76 00:05:24,780 --> 00:05:27,530 We're then redirected to the Comic Books page 77 00:05:27,530 --> 00:05:31,140 which displays a message confirming the comic book deletion. 78 00:05:31,140 --> 00:05:34,520 We can also see that Issue Number 5 of the Bone Series 79 00:05:34,520 --> 00:05:36,530 is no longer in the list of Comic Books. 80 00:05:37,730 --> 00:05:42,770 With those changes completed, we can now create, update, and delete comic books. 81 00:05:42,770 --> 00:05:44,500 Nice work making progress on our web app. 82 00:05:45,510 --> 00:05:48,260 It's worth noting that our approach for deleting a comic book 83 00:05:48,260 --> 00:05:52,930 relies upon cascade deletes to delete the related comic book artist records. 84 00:05:52,930 --> 00:05:57,420 This works fine for comic books, but for artists or series, we may not want 85 00:05:57,420 --> 00:06:02,030 users to be able to delete a large number of related comic book records. 86 00:06:02,030 --> 00:06:05,890 Let's look at a couple of alternative strategies for handling deletes. 87 00:06:05,890 --> 00:06:09,350 One option would be to retrieve and display related data 88 00:06:09,350 --> 00:06:12,638 on the detail page for a record that the user is trying to delete. 89 00:06:12,638 --> 00:06:15,160 For instance, under Artist Detail page, 90 00:06:15,160 --> 00:06:19,160 we would display all of the comic books that the artist is associated with. 91 00:06:19,160 --> 00:06:21,300 We could then disable the Delete button, and 92 00:06:21,300 --> 00:06:25,840 display a tool tip that lets the user know that the artist must first be removed from 93 00:06:25,840 --> 00:06:29,290 all of the listed comic books before the artist can be deleted. 94 00:06:29,290 --> 00:06:32,150 This is much more of a conservative approach than just 95 00:06:32,150 --> 00:06:34,310 letting the cascade deletes happen. 96 00:06:34,310 --> 00:06:37,320 But while it prevents the deletion of records that are in use, 97 00:06:37,320 --> 00:06:41,480 it does give the user the information that they need in order to move forward. 98 00:06:41,480 --> 00:06:46,000 If they, in fact, need to actually delete the record in question, another option 99 00:06:46,000 --> 00:06:50,180 would be to allow the user to delete the records, even if they are in use. 100 00:06:50,180 --> 00:06:53,380 But instead of physically deleting the record from the database, 101 00:06:53,380 --> 00:06:55,870 we simply mark the record as deleted. 102 00:06:55,870 --> 00:07:00,320 This is typically done by setting an active property to the value of false. 103 00:07:00,320 --> 00:07:03,640 These kinds of deletes are known as Logical Deletes. 104 00:07:03,640 --> 00:07:06,330 Allowing users to perform Logical Deletes 105 00:07:06,330 --> 00:07:10,200 give developers a way to grant users more power in the application 106 00:07:10,200 --> 00:07:13,520 while still retaining some level of control over the data. 107 00:07:13,520 --> 00:07:16,454 For example, a user might delete a record, 108 00:07:16,454 --> 00:07:20,431 only to realize later that they shouldn't have done that. 109 00:07:20,431 --> 00:07:24,383 To undo the deletion, they could contact an administrator or 110 00:07:24,383 --> 00:07:26,342 superuser do it in turn. 111 00:07:26,342 --> 00:07:30,710 Use a special page to search for and undeleted the deleted record. 112 00:07:30,710 --> 00:07:32,660 By saving this active property back to a value of true. 113 00:07:32,660 --> 00:07:37,150 Logical Deletes seem too good to be true, right? 114 00:07:37,150 --> 00:07:39,780 Well, there are some draw backs to be aware of. 115 00:07:39,780 --> 00:07:43,670 If your web app requires users to delete large numbers of records, 116 00:07:43,670 --> 00:07:46,520 your database can grow unexpectantly large, 117 00:07:46,520 --> 00:07:50,610 as deleted records are never actually removed from the database. 118 00:07:50,610 --> 00:07:54,240 Another draw back is that most of your queries will need to filter 119 00:07:54,240 --> 00:07:57,340 out records who's active values are false. 120 00:07:57,340 --> 00:08:01,690 Otherwise, list pages in the web app might unintentionally contain deleted records. 121 00:08:02,710 --> 00:08:04,522 None of these issues are insurmountable. 122 00:08:04,522 --> 00:08:07,580 There are simply things you need to consider when you're deciding 123 00:08:07,580 --> 00:08:09,840 how you handle deletes in your web app. 124 00:08:09,840 --> 00:08:14,410 Furthermore, you can even mix and match approaches within the same app. 125 00:08:14,410 --> 00:08:17,260 Critical record types could use logical deletes, 126 00:08:17,260 --> 00:08:19,620 while other record types could use physical deletes. 127 00:08:20,770 --> 00:08:24,370 Coming up next, we'll review the Comic Book Artist Controller, and 128 00:08:24,370 --> 00:08:27,150 give you a chance to finish implementing it on your own.