Samouczek: implementowanie funkcji CRUD za pomocą platformy Entity Framework w ASP.NET MVC
W poprzednim samouczku utworzono aplikację MVC, która przechowuje i wyświetla dane przy użyciu programu Entity Framework (EF) 6 i programu SQL Server LocalDB. W tym samouczku zapoznasz się i dostosujesz kod tworzenia, odczytu, aktualizowania, usuwania (CRUD), który szkielet MVC tworzy automatycznie w kontrolerach i widokach.
Uwaga
Typowym rozwiązaniem jest zaimplementowanie wzorca repozytorium w celu utworzenia warstwy abstrakcji między kontrolerem a warstwą dostępu do danych. Aby zachować prostotę tych samouczków i skupić się na nauce korzystania z samej platformy EF 6, nie używają repozytoriów. Aby uzyskać informacje o sposobie implementowania repozytoriów, zobacz ASP.NET Mapa zawartości dostępu do danych.
Oto przykłady tworzonych stron internetowych:
W tym samouczku zostały wykonane następujące czynności:
- Tworzenie strony Szczegóły
- Aktualizowanie strony Tworzenie
- Aktualizowanie metody HttpPost Edit
- Aktualizowanie strony Usuwanie
- Zamykanie połączeń bazy danych
- Obsługa transakcji
Wymagania wstępne
Tworzenie strony Szczegóły
Kod szkieletu strony Uczniowie Index
pominął Enrollments
właściwość, ponieważ ta właściwość zawiera kolekcję. Details
Na stronie zostanie wyświetlona zawartość kolekcji w tabeli HTML.
W obszarze Controllers\StudentController.cs metoda akcji widoku Details
używa metody Find do pobrania pojedynczej Student
jednostki.
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Student student = db.Students.Find(id);
if (student == null)
{
return HttpNotFound();
}
return View(student);
}
Wartość klucza jest przekazywana do metody jako parametru id
i pochodzi z danych trasy w hiperlinku Szczegóły na stronie Indeks.
Porada: Dane trasy
Dane trasy to dane, które powiązanie modelu można znaleźć w segmencie adresu URL określonym w tabeli routingu. Na przykład trasa domyślna określa controller
, action
i id
segmenty:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
W poniższym adresie URL domyślna trasa mapuje Instructor
jako controller
wartości , Index
jako action
wartości i 1 id
. Są to wartości danych trasy.
http://localhost:1230/Instructor/Index/1?courseID=2021
?courseID=2021
jest wartością ciągu zapytania. Powiązanie modelu będzie również działać w przypadku przekazania id
wartości ciągu zapytania:
http://localhost:1230/Instructor/Index?id=1&CourseID=2021
Adresy URL są tworzone przez ActionLink
instrukcje w widoku Razor. W poniższym kodzie id
parametr jest zgodny z trasą domyślną, dlatego id
jest dodawany do danych trasy.
@Html.ActionLink("Select", "Index", new { id = item.PersonID })
W poniższym kodzie courseID
parametr nie jest zgodny z parametrem w trasie domyślnej, dlatego jest dodawany jako ciąg zapytania.
@Html.ActionLink("Select", "Index", new { courseID = item.CourseID })
Aby utworzyć stronę Szczegóły
Otwórz plik Views\Student\Details.cshtml.
Każde pole jest wyświetlane przy użyciu
DisplayFor
pomocnika, jak pokazano w poniższym przykładzie:<dt> @Html.DisplayNameFor(model => model.LastName) </dt> <dd> @Html.DisplayFor(model => model.LastName) </dd>
EnrollmentDate
Po polu i bezpośrednio przed tagiem zamykającym</dl>
dodaj wyróżniony kod, aby wyświetlić listę rejestracji, jak pokazano w poniższym przykładzie:<dt> @Html.DisplayNameFor(model => model.EnrollmentDate) </dt> <dd> @Html.DisplayFor(model => model.EnrollmentDate) </dd> <dt> @Html.DisplayNameFor(model => model.Enrollments) </dt> <dd> <table class="table"> <tr> <th>Course Title</th> <th>Grade</th> </tr> @foreach (var item in Model.Enrollments) { <tr> <td> @Html.DisplayFor(modelItem => item.Course.Title) </td> <td> @Html.DisplayFor(modelItem => item.Grade) </td> </tr> } </table> </dd> </dl> </div> <p> @Html.ActionLink("Edit", "Edit", new { id = Model.ID }) | @Html.ActionLink("Back to List", "Index") </p>
Jeśli wcięcie kodu jest nieprawidłowe po wklejeniu kodu, naciśnij Ctrl K, Ctrl++D, aby go sformatować.
Ten kod przechodzi przez jednostki we
Enrollments
właściwości nawigacji. Dla każdejEnrollment
jednostki we właściwości wyświetla tytuł kursu i ocenę. Tytuł kursu jest pobierany zCourse
jednostki przechowywanejCourse
we właściwościEnrollments
nawigacji jednostki. Wszystkie te dane są pobierane z bazy danych automatycznie, gdy są potrzebne. Innymi słowy, używasz tutaj leniwego ładowania. Nie określono chętnegoCourses
ładowania dla właściwości nawigacji, więc rejestracje nie zostały pobrane w tym samym zapytaniu, które pobrało uczniów. Zamiast tego przy pierwszej próbie uzyskania dostępuEnrollments
do właściwości nawigacji nowe zapytanie jest wysyłane do bazy danych w celu pobrania danych. Więcej informacji na temat leniwego ładowania i chętnego ładowania można przeczytać w samouczku Reading Related Data (Odczytywanie powiązanych danych ) w dalszej części tej serii.Otwórz stronę Szczegóły, uruchamiając program (Ctrl+F5), wybierając kartę Uczniowie , a następnie klikając link Szczegóły dla Alexander Carson. (Jeśli naciskasz Ctrl+F5, gdy plik Details.cshtml jest otwarty, występuje błąd HTTP 400. Dzieje się tak, ponieważ program Visual Studio próbuje uruchomić stronę Szczegóły, ale nie został osiągnięty z linku określającego ucznia do wyświetlenia. Jeśli tak się stanie, usuń ciąg "Student/Details" z adresu URL i spróbuj ponownie lub zamknij przeglądarkę, kliknij prawym przyciskiem myszy projekt, a następnie kliknij polecenie Wyświetl>widok w przeglądarce.
Zostanie wyświetlona lista kursów i ocen dla wybranego ucznia.
Zamknij okno przeglądarki.
Aktualizowanie strony Tworzenie
W obszarze Controllers\StudentController.cs zastąp metodę HttpPostAttribute
Create
akcji poniższym kodem. Ten kod dodajetry-catch
blok i usuwaID
element z atrybutu BindAttribute dla metody szkieletowej:[HttpPost] [ValidateAntiForgeryToken] public ActionResult Create([Bind(Include = "LastName, FirstMidName, EnrollmentDate")]Student student) { try { if (ModelState.IsValid) { db.Students.Add(student); db.SaveChanges(); return RedirectToAction("Index"); } } catch (DataException /* dex */) { //Log the error (uncomment dex variable name and add a line here to write a log. ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator."); } return View(student); }
Ten kod dodaje
Student
jednostkę utworzoną przez powiązanie modelu MVC ASP.NET z zestawemStudents
jednostek, a następnie zapisuje zmiany w bazie danych. Binder modelu odnosi się do ASP.NET funkcji MVC, która ułatwia pracę z danymi przesłanymi przez formularz; binder modelu konwertuje opublikowane wartości formularza na typy CLR i przekazuje je do metody akcji w parametrach. W takim przypadku binder modelu tworzy wystąpienieStudent
jednostki przy użyciu wartości właściwości zForm
kolekcji.Usunięto
ID
element z atrybutu Bind, ponieważID
jest to wartość klucza podstawowego, którą program SQL Server ustawi automatycznie po wstawieniu wiersza. Dane wejściowe od użytkownika nie ustawiająID
wartości.Ostrzeżenie o zabezpieczeniach —
ValidateAntiForgeryToken
atrybut pomaga zapobiegać fałszerzowaniu żądań między witrynami . Wymaga ona odpowiedniejHtml.AntiForgeryToken()
instrukcji w widoku, którą zobaczysz później.Atrybut
Bind
jest jednym ze sposobów ochrony przed nadmiernym publikowaniem w scenariuszach tworzenia. Załóżmy na przykład, żeStudent
jednostka zawieraSecret
właściwość, której nie chcesz ustawić na tej stronie sieci Web.public class Student { public int ID { get; set; } public string LastName { get; set; } public string FirstMidName { get; set; } public DateTime EnrollmentDate { get; set; } public string Secret { get; set; } public virtual ICollection<Enrollment> Enrollments { get; set; } }
Nawet jeśli nie masz
Secret
pola na stronie internetowej, haker może użyć narzędzia takiego jak fiddler lub napisać jakiś kod JavaScript, aby opublikowaćSecret
wartość formularza. BindAttribute Bez ograniczania pól używanych przez powiązanie modelu podczas tworzeniaStudent
wystąpienia, powiązanie modelu będzie pobierać wartośćSecret
tego formularza i używać go do tworzeniaStudent
wystąpienia jednostki. Następnie dowolna wartość określona przez hakeraSecret
dla pola formularza zostanie zaktualizowana w bazie danych. Na poniższej ilustracji przedstawiono narzędzie fiddler dodająceSecret
pole (z wartością "OverPost") do opublikowanych wartości formularza.Następnie wartość "OverPost" zostanie pomyślnie dodana do
Secret
właściwości wstawionego wiersza, chociaż nigdy nie zamierzano ustawiać tej właściwości na stronie internetowej.Najlepiej użyć parametru
Include
z atrybutemBind
, aby jawnie wyświetlić listę pól. Można również użyć parametruExclude
, aby zablokować pola, które chcesz wykluczyć. PowodemInclude
jest to, że po dodaniu nowej właściwości do jednostki nowe pole nie jest automatycznie chronione przezExclude
listę.Aby zapobiec przesłaniu w scenariuszach edycji, należy najpierw odczytać jednostkę z bazy danych, a następnie wywołać metodę
TryUpdateModel
, przekazując jawnie dozwoloną listę właściwości. Jest to metoda używana w tych samouczkach.Alternatywnym sposobem zapobiegania przesłonięć preferowanym przez wielu deweloperów jest użycie modeli wyświetlania, a nie klas jednostek z powiązaniem modelu. Uwzględnij tylko właściwości, które chcesz zaktualizować w modelu widoku. Po zakończeniu powiązania modelu MVC skopiuj właściwości modelu widoku do wystąpienia jednostki, opcjonalnie przy użyciu narzędzia takiego jak AutoMapper. Użyj bazy danych. Wpis w wystąpieniu jednostki, aby ustawić jego stan na Niezmienione, a następnie ustaw właściwość("PropertyName"). Właściwość IsModified ma wartość true dla każdej właściwości jednostki uwzględnionej w modelu widoku. Ta metoda działa zarówno w scenariuszach edycji, jak i tworzenia.
Poza atrybutem
Bind
try-catch
blok jest jedyną zmianą wprowadzaną w kodzie szkieletowym. Jeśli podczas zapisywania zmian zostanie przechwycony DataException wyjątek, z którego pochodzą zmiany, zostanie wyświetlony ogólny komunikat o błędzie. DataException wyjątki są czasami spowodowane przez coś zewnętrznego dla aplikacji, a nie błąd programowania, dlatego zaleca się, aby użytkownik próbował ponownie. Chociaż nie zaimplementowano w tym przykładzie, aplikacja jakości produkcyjnej rejestruje wyjątek. Aby uzyskać więcej informacji, zobacz sekcję Dziennik dla szczegółowych informacji w temacie Monitorowanie i telemetria (tworzenie rzeczywistych aplikacji w chmurze za pomocą platformy Azure).Kod w pliku Views\Student\Create.cshtml jest podobny do tego, co zostało wyświetlone w pliku Details.cshtml, z tą różnicą, że
EditorFor
iValidationMessageFor
pomocnicy są używane dla każdego pola zamiastDisplayFor
. Oto odpowiedni kod:<div class="form-group"> @Html.LabelFor(model => model.LastName, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.LastName) @Html.ValidationMessageFor(model => model.LastName) </div> </div>
Plik Create.cshtml zawiera
@Html.AntiForgeryToken()
również element , który współdziała z atrybutemValidateAntiForgeryToken
w kontrolerze, aby zapobiec atakom fałszerzowania żądań między witrynami .W pliku Create.cshtml nie są wymagane żadne zmiany.
Uruchom stronę, uruchamiając program, wybierając kartę Uczniowie , a następnie klikając pozycję Utwórz nowy.
Wprowadź nazwy i nieprawidłową datę, a następnie kliknij przycisk Utwórz , aby wyświetlić komunikat o błędzie.
Jest to weryfikacja po stronie serwera, która jest domyślnie pobierana. W późniejszym samouczku dowiesz się, jak dodać atrybuty generujące kod na potrzeby weryfikacji po stronie klienta. Poniższy wyróżniony kod przedstawia sprawdzanie poprawności modelu w metodzie Create .
if (ModelState.IsValid) { db.Students.Add(student); db.SaveChanges(); return RedirectToAction("Index"); }
Zmień datę na prawidłową wartość i kliknij przycisk Utwórz , aby wyświetlić nowego ucznia na stronie Indeks .
Zamknij okno przeglądarki.
Aktualizowanie metody HttpPost Edit
Zastąp metodę HttpPostAttribute
Edit
akcji następującym kodem:[HttpPost, ActionName("Edit")] [ValidateAntiForgeryToken] public ActionResult EditPost(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } var studentToUpdate = db.Students.Find(id); if (TryUpdateModel(studentToUpdate, "", new string[] { "LastName", "FirstMidName", "EnrollmentDate" })) { try { db.SaveChanges(); return RedirectToAction("Index"); } catch (DataException /* dex */) { //Log the error (uncomment dex variable name and add a line here to write a log. ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator."); } } return View(studentToUpdate); }
Uwaga
W controllers\StudentController.cs
HttpGet Edit
metoda (ta bez atrybutuHttpPost
) używaFind
metody do pobrania wybranejStudent
jednostki, jak pokazano w metodzieDetails
. Nie musisz zmieniać tej metody.Te zmiany implementują najlepsze rozwiązanie w zakresie zabezpieczeń, aby zapobiec przesłaniu, szkielet wygenerował atrybut i dodał jednostkę utworzoną
Bind
przez binder modelu do zestawu jednostek z flagą Zmodyfikowana. Ten kod nie jest już zalecany, ponieważBind
atrybut usuwa wszystkie istniejące dane w polach, które nie są wymienione w parametrzeInclude
. W przyszłości szkielet kontrolera MVC zostanie zaktualizowany tak, aby nie generowałBind
atrybutów dla metod Edycji.Nowy kod odczytuje istniejącą jednostkę i wywołuje metodę TryUpdateModel aktualizowania pól z danych wejściowych użytkownika w opublikowanych danych formularza. Automatyczne śledzenie zmian w programie Entity Framework ustawia flagę EntityState.Modified w jednostce. Po wywołaniu metody SaveChanges flaga Modified powoduje, że program Entity Framework tworzy instrukcje SQL w celu zaktualizowania wiersza bazy danych. Konflikty współbieżności są ignorowane, a wszystkie kolumny wiersza bazy danych są aktualizowane, w tym te, które użytkownik nie zmienił. (W późniejszym samouczku pokazano, jak obsługiwać konflikty współbieżności, a jeśli chcesz zaktualizować tylko poszczególne pola w bazie danych, możesz ustawić jednostkę na EntityState.Bez zmian i ustaw poszczególne pola na EntityState.Modified.
Aby zapobiec przesłanianiu, pola, które mają być aktualizowane przez stronę Edytuj, są wymienione w parametrach
TryUpdateModel
. Obecnie nie ma dodatkowych pól, które są chronione, ale wyświetlanie listy pól, które mają zostać powiązane z powiązaniem modelu, gwarantuje, że w przypadku dodawania pól do modelu danych są one automatycznie chronione do momentu jawnego dodania ich w tym miejscu.W wyniku tych zmian sygnatura metody HttpPost Edit jest taka sama jak metoda edycji HttpGet; w związku z tym zmieniono nazwę metody EditPost.
Napiwek
Stany jednostek oraz metody Attach i SaveChanges
Kontekst bazy danych śledzi, czy jednostki w pamięci są zsynchronizowane z odpowiednimi wierszami w bazie danych, a te informacje określają, co się stanie po wywołaniu
SaveChanges
metody. Na przykład po przekazaniu nowej jednostki do metody Add stan tej jednostki jest ustawiony naAdded
wartość . Następnie po wywołaniu metody SaveChanges kontekst bazy danych wystawia polecenie SQLINSERT
.Jednostka może znajdować się w jednym z następujących stanów:
Added
. Jednostka nie istnieje jeszcze w bazie danych. MetodaSaveChanges
musi wydać instrukcjęINSERT
.Unchanged
. W tej jednostceSaveChanges
nie trzeba nic robić przy użyciu metody . Podczas odczytywania jednostki z bazy danych jednostka zaczyna się od tego stanu.Modified
. Niektóre lub wszystkie wartości właściwości jednostki zostały zmodyfikowane. MetodaSaveChanges
musi wydać instrukcjęUPDATE
.Deleted
. Jednostka została oznaczona do usunięcia. MetodaSaveChanges
musi wydać instrukcjęDELETE
.Detached
. Jednostka nie jest śledzona przez kontekst bazy danych.
W aplikacji klasycznej zmiany stanu są zwykle ustawiane automatycznie. W typie aplikacji klasycznej odczytujesz jednostkę i wprowadzasz zmiany w niektórych jej wartościach właściwości. Powoduje to automatyczne zmianę stanu jednostki na
Modified
. Następnie po wywołaniuSaveChanges
metody program Entity Framework generuje instrukcję SQLUPDATE
, która aktualizuje tylko rzeczywiste właściwości, które uległy zmianie.Rozłączony charakter aplikacji internetowych nie zezwala na tę sekwencję ciągłą. Obiekt DbContext odczytujący jednostkę jest usuwany po renderowaniu strony. Po wywołaniu
HttpPost
Edit
metody akcji zostanie wykonane nowe żądanie i masz nowe wystąpienie obiektu DbContext, dlatego należy ręcznie ustawić stan jednostki naModified.
Wartość Następnie po wywołaniuSaveChanges
programu Entity Framework aktualizuje wszystkie kolumny wiersza bazy danych, ponieważ kontekst nie ma możliwości poznania, które właściwości zostały zmienione.Jeśli chcesz, aby instrukcja SQL
Update
aktualizowała tylko pola, które użytkownik rzeczywiście zmienił, możesz zapisać oryginalne wartości w jakiś sposób (na przykład ukryte pola), aby były dostępne po wywołaniuHttpPost
Edit
metody. Następnie możesz utworzyć jednostkę przy użyciu oryginalnych wartości, wywołaćAttach
metodęStudent
z tą oryginalną wersją jednostki, zaktualizować wartości jednostki do nowych wartości, a następnie wywołać metodęSaveChanges.
Aby uzyskać więcej informacji, zobacz Stany jednostki i SaveChanges i Dane lokalne.Kod HTML i Razor w pliku Views\Student\Edit.cshtml jest podobny do tego, co zostało wyświetlone w pliku Create.cshtml i nie są wymagane żadne zmiany.
Uruchom stronę, uruchamiając program, wybierając kartę Uczniowie , a następnie klikając hiperlink Edytuj .
Zmień niektóre dane i kliknij przycisk Zapisz. Zmienione dane są widoczne na stronie Indeks.
Zamknij okno przeglądarki.
Aktualizowanie strony Usuwanie
W obszarze Controllers\StudentController.cs kod szablonu metody HttpGetAttribute Delete
używa Find
metody do pobrania wybranej Student
jednostki, jak pokazano w metodach Details
i Edit
. Jednak aby zaimplementować niestandardowy komunikat o błędzie, gdy wywołanie zakończy się SaveChanges
niepowodzeniem, do tej metody dodasz pewne funkcje i odpowiadający jej widok.
Jak pokazano na potrzeby operacji aktualizacji i tworzenia, operacje usuwania wymagają dwóch metod akcji. Metoda wywoływana w odpowiedzi na żądanie GET wyświetla widok, który daje użytkownikowi szansę zatwierdzenia lub anulowania operacji usuwania. Jeśli użytkownik go zatwierdzi, zostanie utworzone żądanie POST. W takim przypadku metoda jest wywoływana, HttpPost
Delete
a następnie metoda faktycznie wykonuje operację usuwania.
Do metody dodasz try-catch
blok, HttpPostAttribute Delete
aby obsłużyć wszelkie błędy, które mogą wystąpić po zaktualizowaniu bazy danych. Jeśli wystąpi błąd, HttpPostAttribute Delete
metoda wywołuje metodę HttpGetAttribute Delete
, przekazując jej parametr wskazujący, że wystąpił błąd. Następnie HttpGetAttribute Delete
metoda redisplays strony potwierdzenia wraz z komunikatem o błędzie, dając użytkownikowi możliwość anulowania lub próby ponownie.
Zastąp metodę HttpGetAttribute
Delete
akcji następującym kodem, który zarządza raportowaniem błędów:public ActionResult Delete(int? id, bool? saveChangesError=false) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } if (saveChangesError.GetValueOrDefault()) { ViewBag.ErrorMessage = "Delete failed. Try again, and if the problem persists see your system administrator."; } Student student = db.Students.Find(id); if (student == null) { return HttpNotFound(); } return View(student); }
Ten kod akceptuje opcjonalny parametr wskazujący, czy metoda została wywołana po niepowodzeniu zapisywania zmian. Ten parametr występuje
false
, gdyHttpGet
Delete
metoda jest wywoływana bez wcześniejszego błędu. Gdy jest wywoływana przez metodęHttpPost
Delete
w odpowiedzi na błąd aktualizacji bazy danych, parametr jesttrue
i komunikat o błędzie jest przekazywany do widoku.Zastąp metodę HttpPostAttribute
Delete
akcji (o nazwieDeleteConfirmed
) następującym kodem, który wykonuje rzeczywistą operację usuwania i przechwytuje wszelkie błędy aktualizacji bazy danych.[HttpPost] [ValidateAntiForgeryToken] public ActionResult Delete(int id) { try { Student student = db.Students.Find(id); db.Students.Remove(student); db.SaveChanges(); } catch (DataException/* dex */) { //Log the error (uncomment dex variable name and add a line here to write a log. return RedirectToAction("Delete", new { id = id, saveChangesError = true }); } return RedirectToAction("Index"); }
Ten kod pobiera wybraną jednostkę, a następnie wywołuje metodę Remove , aby ustawić stan jednostki na
Deleted
. PoSaveChanges
wywołaniu jest generowane polecenie SQLDELETE
. Zmieniono również nazwę metody akcji zDeleteConfirmed
naDelete
. Kod szkieletowy o nazwieHttpPost
Delete
metodyDeleteConfirmed
w celu nadania metodzieHttpPost
unikatowego podpisu. (ClR wymaga przeciążonych metod, aby mieć różne parametry metody). Teraz, gdy podpisy są unikatowe, możesz trzymać się konwencji MVC i używać tej samej nazwy dlaHttpPost
metod iHttpGet
usuwania.Jeśli zwiększenie wydajności w aplikacji o dużej ilości jest priorytetem, można uniknąć niepotrzebnego zapytania SQL w celu pobrania wiersza, zastępując wiersze kodu, które wywołają
Find
metody iRemove
następującym kodem:Student studentToDelete = new Student() { ID = id }; db.Entry(studentToDelete).State = EntityState.Deleted;
Ten kod tworzy wystąpienie
Student
jednostki przy użyciu tylko wartości klucza podstawowego, a następnie ustawia stan jednostki naDeleted
. To wszystko, co wymaga program Entity Framework w celu usunięcia jednostki.Jak wspomniano,
HttpGet
Delete
metoda nie usuwa danych. Wykonanie operacji usuwania w odpowiedzi na żądanie GET (lub w tym przypadku wykonanie dowolnej operacji edycji, operacji tworzenia lub dowolnej innej operacji, która zmienia dane) powoduje zagrożenie bezpieczeństwa.W pliku Views\Student\Delete.cshtml dodaj komunikat o błędzie między nagłówkiem
h2
a nagłówkiemh3
, jak pokazano w poniższym przykładzie:<h2>Delete</h2> <p class="error">@ViewBag.ErrorMessage</p> <h3>Are you sure you want to delete this?</h3>
Uruchom stronę, uruchamiając program, wybierając kartę Uczniowie , a następnie klikając hiperlink Usuń .
Wybierz pozycję Usuń na stronie z informacją Czy na pewno chcesz to usunąć?.
Strona Indeks jest wyświetlana bez usuniętego ucznia. (W samouczku współbieżności zostanie wyświetlony przykład kodu obsługi błędów).
Zamykanie połączeń bazy danych
Aby zamknąć połączenia z bazą danych i zwolnić przechowywane zasoby tak szybko, jak to możliwe, należy usunąć wystąpienie kontekstu po zakończeniu pracy z nim. Dlatego kod szkieletowy udostępnia metodę Dispose na końcu StudentController
klasy w StudentController.cs, jak pokazano w poniższym przykładzie:
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
Klasa bazowa Controller
już implementuje IDisposable
interfejs, więc ten kod po prostu dodaje przesłonięcia do Dispose(bool)
metody w celu jawnego usunięcia wystąpienia kontekstu.
Obsługa transakcji
Domyślnie program Entity Framework niejawnie implementuje transakcje. W scenariuszach, w których wprowadzasz zmiany w wielu wierszach lub tabelach, a następnie wywołujesz SaveChanges
metodę , program Entity Framework automatycznie upewnia się, że wszystkie zmiany kończą się powodzeniem lub wszystkimi niepowodzeniem. Jeśli najpierw zostaną wykonane pewne zmiany, a następnie wystąpi błąd, te zmiany zostaną automatycznie wycofane. W przypadku scenariuszy, w których potrzebujesz większej kontroli — na przykład jeśli chcesz uwzględnić operacje wykonywane poza programem Entity Framework w transakcji, zobacz Praca z transakcjami.
Uzyskiwanie kodu
Pobieranie ukończonego projektu
Dodatkowe zasoby
Masz teraz kompletny zestaw stron, które wykonują proste operacje CRUD dla Student
jednostek. Użyto pomocników MVC do generowania elementów interfejsu użytkownika dla pól danych. Aby uzyskać więcej informacji na temat pomocników MVC, zobacz Renderowanie formularza przy użyciu pomocników HTML (artykuł dotyczy wzorca MVC 3, ale jest nadal odpowiedni dla MVC 5).
Linki do innych zasobów ef 6 można znaleźć w ASP.NET Dostęp do danych — zalecane zasoby.
Następne kroki
W tym samouczku zostały wykonane następujące czynności:
- Utworzono stronę Szczegóły
- Zaktualizowano stronę Tworzenie
- Zaktualizowano metodę HttpPost Edit
- Zaktualizowano stronę Usuwanie
- Zamknięte połączenia z bazą danych
- Obsługiwane transakcje
Przejdź do następnego artykułu, aby dowiedzieć się, jak dodać sortowanie, filtrowanie i stronicowanie do projektu.