Samouczek: implementowanie funkcji CRUD za pomocą platformy Entity Framework w ASP.NET MVC

W poprzednim samouczku utworzyłeś 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 przejrzysz i dostosujesz kod operacji tworzenia, odczytu, aktualizacji i usuwania (CRUD), który mechanizm rusztowania MVC automatycznie generuje w kontrolerach i widokach.

Uwaga

Powszechną praktyką jest wdrożenie wzorca repozytorium w celu utworzenia warstwy abstrakcji między kontrolerem a warstwą dostępu do danych. Aby te samouczki były proste i skupiały się na pokazaniu, jak korzystać z samego EF 6, nie korzysta się w nich z repozytoriów. Aby uzyskać informacje o sposobie implementowania repozytoriów, zobacz Mapa zawartości dostępu do danych ASP.NET.

Oto przykłady stron internetowych, które tworzysz:

Zrzut ekranu przedstawiający stronę szczegółów ucznia.

Zrzut ekranu przedstawiający stronę tworzenia ucznia.

Zrzut ekranu przedstawiający stronę usuwania ucznia.

W tym samouczku:

  • Utwórz stronę „Szczegóły”
  • Zaktualizuj stronę Tworzenie
  • Zaktualizuj metodę HttpPost Edit
  • Zaktualizuj stronę „Usuwanie”
  • Zamknij połączenia z bazą danych
  • Obsługuj transakcje

Wymagania wstępne

Utwórz stronę „Szczegóły”

Kod szkieletu strony Uczniowie Index pominął Enrollments właściwość, ponieważ ta właściwość zawiera kolekcję. Na stronie Details zostanie wyświetlona zawartość kolekcji w tabeli HTML.

W pliku Controllers\StudentController.cs metoda akcji dla widoku Details używa metody Find do pobrania pojedynczej jednostki Student.

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 parametr id i pochodzi z danych routingu w hiperlinku Szczegóły na stronie Indeks.

Wskazówka: Dane trasy

Dane trasy to dane, które binder modelu znalazł w segmencie adresu URL określonym w tabeli routingu. Na przykład trasa domyślna określa controller, actioni 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, Index jako action i 1 jako id; są to wartości danych trasy.

http://localhost:1230/Instructor/Index/1?courseID=2021

?courseID=2021 jest wartością query string. Mechanizm wiązania modelu będzie również działać w przypadku przekazania wartości id jako parametru zapytania:

http://localhost:1230/Instructor/Index?id=1&CourseID=2021

Adresy URL są tworzone za pomocą instrukcji ActionLink 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 element courseID nie odpowiada parametrowi w trasie domyślnej, dlatego jest dodawany jako ciąg zapytania.

@Html.ActionLink("Select", "Index", new { courseID = item.CourseID })

Aby utworzyć stronę „Szczegóły”

  1. 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>
    
  2. Po polu EnrollmentDate 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, CtrlD, aby go sformatować.

    Ten kod iteruje po encjach we właściwości nawigacji Enrollments. Dla każdej Enrollment encji we właściwości wyświetla tytuł kursu i ocenę. Tytuł kursu jest pobierany z encji Course, która jest przechowywana we właściwości nawigacji Course encji Enrollments. Wszystkie te dane są pobierane z bazy danych automatycznie, gdy są potrzebne. Innymi słowy, używasz tutaj leniwego ładowania. Nie określono Courses dla właściwości nawigacji, więc zapisy nie zostały pobrane w tym samym zapytaniu, które pobrało uczniów. Zamiast tego przy pierwszej próbie uzyskania dostępu Enrollments 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 ładowania zachłannego można przeczytać w samouczku Reading Related Data w dalszej części tej serii.

  3. 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.

  4. Zamknij przeglądarkę.

Zaktualizuj stronę „Tworzenie”

  1. W pliku Controllers\StudentController.cs zastąp metodę akcji HttpPostAttributeCreate poniższym kodem. Ten kod dodaje try-catch blok i usuwa ID 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 zestawem Students 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ąpienie Student jednostki przy użyciu wartości właściwości z Form 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 odpowiedniej Html.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, że encja Student zawiera właściwość Secret, 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 tworzenia Student wystąpienia, powiązanie modelu będzie pobierać wartość Secret tego formularza i używać go do tworzenia Student wystąpienia jednostki. Następnie dowolna wartość określona przez hakera Secret dla pola formularza zostanie zaktualizowana w bazie danych. Na poniższej ilustracji przedstawiono narzędzie fiddler dodające Secret pole (z wartością "OverPost") do opublikowanych wartości formularza.

    Zrzut ekranu przedstawiający kartę Composer (Kompozytor). W prawym górnym rogu polecenie Wykonaj jest zakreśline na czerwono. W prawym dolnym rogu wpis tajny jest równy Over Post jest zakreśliny na czerwono.

    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 atrybutem Bind, aby jawnie wymienić pola. Można również użyć parametru Exclude , aby zablokować pola, które chcesz wykluczyć. Powodem Include jest to, że po dodaniu nowej właściwości do jednostki nowe pole nie jest automatycznie chronione przez Exclude 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 db.Entry na wystąpieniu encji, aby ustawić jej stan na Niezmieniony, a następnie ustaw Property("PropertyName").IsModified na true dla każdej właściwości encji uwzględnionej w modelu widoku. Ta metoda działa zarówno w scenariuszach edycji, jak i tworzenia.

    Poza atrybutem Bindtry-catch blok jest jedyną zmianą wprowadzaną w kodzie szkieletowym. Jeśli podczas zapisywania zmian zostanie przechwycony wyjątek dziedziczący po DataException, zostanie wyświetlony ogólny komunikat o błędzie. DataException wyjątki są czasami spowodowane przez coś zewnętrznego dla aplikacji, a nie przez 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 szczegółowych informacji w 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 i ValidationMessageFor pomocnicy są używane dla każdego pola zamiast DisplayFor. 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 również @Html.AntiForgeryToken(), który współdziała z atrybutem ValidateAntiForgeryToken w kontrolerze, aby zapobiec atakom fałszerzowania żądań między witrynami.

    W pliku Create.cshtml nie są wymagane żadne zmiany.

  2. Otwórz stronę, uruchamiając program, wybierając kartę Uczniowie, a następnie klikając pozycję Utwórz nowy.

  3. 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órą otrzymujesz domyślnie. 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");
    }
    
  4. Zmień datę na poprawną wartość i kliknij przycisk Utwórz, aby zobaczyć nowego ucznia na stronie Indeks.

  5. Zamknij okno przeglądarki.

Aktualizowanie metody HttpPost Edit

  1. Zastąp metodę HttpPostAttributeEdit 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 metoda HttpGet Edit (ta bez atrybutu HttpPost) używa metody Find do pobrania wybranej jednostki Student, jak pokazano w metodzie Details. Nie musisz zmieniać tej metody.

    Te zmiany implementują najlepszą praktykę w zakresie zabezpieczeń, aby zapobiec overpostingowi. Generator szkieletu wygenerował atrybut Bind i dodał do zestawu jednostek jednostkę utworzoną przez binder modelu z flagą Modified. Ten kod nie jest już zalecany, ponieważ Bind atrybut usuwa wszystkie istniejące dane w polach, które nie są wymienione w parametrze Include . W przyszłości szkielet kontrolera MVC zostanie zaktualizowany tak, aby nie generował Bind atrybutów dla metod Edit.

    Nowy kod odczytuje istniejącą jednostkę i wywołuje metodę TryUpdateModel, aby zaktualizować pola na podstawie danych wejściowych użytkownika w przesłanych danych formularza. Automatyczne śledzenie zmian w programie Entity Framework ustawia flagę EntityState.Modified dla encji. Po wywołaniu metody SaveChanges flaga Modified powoduje, że program Entity Framework tworzy instrukcje SQL w celu zaktualizowania wiersza w bazie 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.Unchanged i ustawić poszczególne pola na EntityState.Modified.)

    Aby zapobiec nadmiernemu publikowaniu, 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 przez składnik wiązania 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 na Addedwartość . Następnie po wywołaniu metody SaveChanges kontekst bazy danych wystawia polecenie SQL INSERT .

    Jednostka może znajdować się w jednym z następujących stanów:

    • Added. Jednostka nie istnieje jeszcze w bazie danych. Metoda SaveChanges musi wydać instrukcję INSERT .
    • Unchanged. W tej jednostce SaveChanges nie trzeba nic robić przy użyciu metody . Podczas odczytywania encji z bazy danych encja ma początkowo ten stan.
    • Modified. Niektóre lub wszystkie wartości właściwości jednostki zostały zmodyfikowane. Metoda SaveChanges musi wydać instrukcję UPDATE .
    • Deleted. Jednostka została oznaczona do usunięcia. Metoda SaveChanges musi wykonać polecenie DELETE.
    • Detached. Jednostka nie jest śledzona przez kontekst bazy danych.

    W aplikacji klasycznej zmiany stanu są zwykle ustawiane automatycznie. W typie aplikacji klasycznej odczytujesz encję i wprowadzasz zmiany w niektórych wartościach jej właściwości. Powoduje to automatyczną zmianę stanu jednostki na Modified. Następnie po wywołaniu SaveChangesmetody program Entity Framework generuje instrukcję SQL UPDATE , która aktualizuje tylko rzeczywiste właściwości, które uległy zmianie.

    Brak ciągłego połączenia w aplikacjach internetowych nie pozwala na taki ciągły przebieg. Obiekt DbContext odczytujący encję jest usuwany po renderowaniu strony. Po wywołaniu HttpPostEdit metody akcji zostanie wykonane nowe żądanie i masz nowe wystąpienie obiektu DbContext, dlatego należy ręcznie ustawić stan jednostki na Modified. Wartość Następnie po wywołaniu SaveChangesprogramu 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 w ukrytych polach), aby były dostępne, gdy metoda HttpPostEdit zostanie wywołana. Następnie możesz utworzyć jednostkę przy użyciu oryginalnych wartości, wywołać Student metodę Attach 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.

  2. Uruchom stronę, uruchamiając program, wybierając kartę Uczniowie , a następnie klikając hiperlink Edytuj .

  3. Zmień niektóre dane i kliknij przycisk Zapisz. Widzisz zmienione dane na stronie Indeks.

  4. Zamknij okno przeglądarki.

Zaktualizuj stronę Usuwanie

W pliku Controllers\StudentController.cs kod szablonu metody HttpGetAttributeDelete używa metody Find do pobrania wybranej encji Student, jak pokazano w metodach Details i Edit. Jednak aby zaimplementować niestandardowy komunikat o błędzie, gdy wywołanie SaveChanges zakończy się 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 HttpPostDelete jest wywoływana, a następnie metoda faktycznie wykonuje operację usuwania.

Dodasz blok try-catch do metody HttpPostAttributeDelete, aby obsłużyć wszelkie błędy, które mogą wystąpić podczas aktualizacji bazy danych. Jeśli wystąpi błąd, metoda HttpPostAttributeDelete wywołuje metodę HttpGetAttributeDelete, przekazując jej parametr wskazujący, że wystąpił błąd. Następnie metoda HttpGetAttributeDelete ponownie wyświetla stronę potwierdzenia wraz z komunikatem o błędzie, dając użytkownikowi możliwość anulowania lub ponowienia próby.

  1. Zastąp metodę HttpGetAttributeDelete 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 , gdy HttpGetDelete metoda jest wywoływana bez wcześniejszego błędu. Gdy jest wywoływana przez metodę HttpPostDelete w odpowiedzi na błąd aktualizacji bazy danych, parametr jest true i komunikat o błędzie jest przekazywany do widoku.

  2. Zastąp metodę HttpPostAttributeDelete akcji (o nazwie DeleteConfirmed) 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. Po SaveChanges wywołaniu jest generowane polecenie SQL DELETE . Zmieniono również nazwę metody akcji z DeleteConfirmed na Delete. Kod szkieletowy o nazwie HttpPostDelete metody DeleteConfirmed w celu nadania metodzie HttpPost unikatowego podpisu. (CLR wymaga, aby przeciążone metody miały różne parametry metody). Teraz, gdy sygnatury są unikatowe, możesz trzymać się konwencji MVC i używać tej samej nazwy dla metod usuwania HttpPost i HttpGet.

    Jeśli zwiększenie wydajności w aplikacji o dużym obciążeniu jest priorytetem, można uniknąć niepotrzebnego zapytania SQL w celu pobrania wiersza, zastępując wiersze kodu, które wywołują metody Find i Remove, następującym kodem:

    Student studentToDelete = new Student() { ID = id };
    db.Entry(studentToDelete).State = EntityState.Deleted;
    

    Ten kod tworzy encję Student przy użyciu tylko wartości klucza podstawowego, a następnie ustawia stan jednostki na Deleted. To wszystko, co wymaga program Entity Framework w celu usunięcia jednostki.

    Jak wspomniano, HttpGetDelete 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.

  3. W pliku Views\Student\Delete.cshtml dodaj komunikat o błędzie między nagłówkiem h2 a nagłówkiem h3 , 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>
    
  4. Uruchom stronę, uruchamiając program, wybierając kartę Uczniowie , a następnie klikając hiperlink Usuń .

  5. Wybierz pozycję Usuń na stronie z informacją Czy na pewno chcesz to usunąć?.

    Strona indeksu jest wyświetlana bez usuniętego ucznia. (W samouczku współbieżności zostanie wyświetlony przykład kodu obsługi błędów).

Zamknij połączenia z bazą danych

Aby zamknąć połączenia z bazą danych i zwolnić przechowywane zasoby tak szybko, jak to możliwe, należy zwolnić instancję kontekstu po zakończeniu pracy z nią. Dlatego kod szkieletowy udostępnia metodę Dispose na końcu klasy StudentController 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 interfejs IDisposable, więc ten kod po prostu dodaje przesłonięcie do metody Dispose(bool), aby jawnie zwolnić instancję kontekstu.

Obsługuj transakcje

Domyślnie Entity Framework niejawnie obsługuje transakcje. W scenariuszach, w których wprowadzasz zmiany w wielu wierszach lub tabelach, a następnie wywołujesz SaveChangesmetodę, program Entity Framework automatycznie upewnia się, że wszystkie zmiany kończą się powodzeniem lub wszystkie kończą się niepowodzeniem. Jeśli najpierw zostaną wykonane pewne zmiany, a następnie wystąpi błąd, te zmiany zostaną automatycznie wycofane. W scenariuszach, w których potrzebujesz większej kontroli — na przykład jeśli chcesz uwzględnić w ramach transakcji operacje wykonywane poza platformą Entity Framework — zobacz Praca z transakcjami.

Dodatkowe zasoby

Masz teraz kompletny zestaw stron, które umożliwiają wykonywanie prostych operacji CRUD dla encji Student. Użyto pomocników MVC do utworzenia 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:

  • Utworzono stronę „Szczegóły”
  • Zaktualizowano stronę „Tworzenie”
  • Zaktualizowano metodę HttpPost „Edit”
  • Zaktualizowano stronę Usuń
  • 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.