Samouczek: używanie procedur asynchronicznych i składowanych z platformą EF w aplikacji MVC ASP.NET
W poprzednich samouczkach przedstawiono sposób odczytywania i aktualizowania danych przy użyciu modelu programowania synchronicznego. W tym samouczku pokazano, jak zaimplementować model programowania asynchronicznego. Kod asynchroniczny może pomóc aplikacji w lepszym korzystaniu z zasobów serwera.
W tym samouczku zobaczysz również, jak używać procedur składowanych do operacji wstawiania, aktualizowania i usuwania w jednostce.
Na koniec ponownie wdrożysz aplikację na platformie Azure wraz ze wszystkimi zmianami bazy danych, które zostały wdrożone od czasu pierwszego wdrożenia.
Na poniższych ilustracjach przedstawiono niektóre strony, z którymi będziesz pracować.
W tym samouczku zostały wykonane następujące czynności:
- Dowiedz się więcej o kodzie asynchronicznym
- Tworzenie kontrolera działu
- Korzystanie z procedur składowanych
- Wdróż na platformie Azure
Wymagania wstępne
Dlaczego warto używać kodu asynchronicznego
Serwer internetowy ma dostępną ograniczoną liczbę wątków, a w sytuacjach dużego obciążenia wszystkie dostępne wątki mogą być używane. W takim przypadku serwer nie może przetworzyć nowych żądań, dopóki wątki nie zostaną zwolnione. W przypadku kodu synchronicznego wiele wątków może być powiązanych, gdy w rzeczywistości nie wykonują żadnej pracy, ponieważ oczekują na ukończenie operacji we/wy. W przypadku kodu asynchronicznego, gdy proces oczekuje na ukończenie operacji we/wy, jego wątek zostanie zwolniony, aby serwer był używany do przetwarzania innych żądań. W rezultacie kod asynchroniczny umożliwia wydajniejsze korzystanie z zasobów serwera, a serwer jest włączony do obsługi większej liczby ruchu bez opóźnień.
We wcześniejszych wersjach platformy .NET pisanie i testowanie kodu asynchronicznego było złożone, podatne na błędy i trudne do debugowania. W programie .NET 4.5 pisanie, testowanie i debugowanie kodu asynchronicznego jest o wiele łatwiejsze, ponieważ zwykle należy napisać kod asynchroniczny, chyba że masz powód, aby nie. Kod asynchroniczny wprowadza niewielką ilość narzutów, ale w przypadku sytuacji niskiego ruchu trafienie wydajności jest niewielkie, podczas gdy w przypadku sytuacji o dużym natężeniu ruchu potencjalna poprawa wydajności jest znacząca.
Aby uzyskać więcej informacji na temat programowania asynchronicznego, zobacz Używanie asynchronicznej obsługi asynchronicznej platformy .NET 4.5 w celu uniknięcia blokowania wywołań.
Tworzenie kontrolera działu
Utwórz kontroler działu w taki sam sposób, w jaki wykonaliśmy wcześniejsze kontrolery, z wyjątkiem tego czasu zaznacz pole wyboru Użyj akcji kontrolera asynchronicznego .
Poniższe wyróżnienia pokazują, co zostało dodane do synchronicznego kodu Index
dla metody, aby było asynchroniczne:
public async Task<ActionResult> Index()
{
var departments = db.Departments.Include(d => d.Administrator);
return View(await departments.ToListAsync());
}
Zastosowano cztery zmiany, aby umożliwić wykonywanie asynchronicznego zapytania bazy danych platformy Entity Framework:
- Metoda jest oznaczona
async
słowem kluczowym, które nakazuje kompilatorowi generowanie wywołań zwrotnych dla części treści metody i automatyczne tworzenieTask<ActionResult>
zwracanego obiektu. - Typ zwracany został zmieniony z
ActionResult
naTask<ActionResult>
. TypTask<T>
reprezentuje bieżącą pracę z wynikiem typuT
. - Słowo
await
kluczowe zostało zastosowane do wywołania usługi internetowej. Gdy kompilator widzi to słowo kluczowe, za kulisami dzieli metodę na dwie części. Pierwsza część kończy się operacją uruchomioną asynchronicznie. Druga część jest umieszczana w metodzie wywołania zwrotnego wywoływanej po zakończeniu operacji. - Wywołano asynchroniczną wersję
ToList
metody rozszerzenia.
Dlaczego instrukcja została departments.ToList
zmodyfikowana, ale nie instrukcja departments = db.Departments
? Przyczyną jest to, że tylko instrukcje, które powodują wysyłanie zapytań lub poleceń do bazy danych, są wykonywane asynchronicznie. Instrukcja departments = db.Departments
konfiguruje zapytanie, ale zapytanie nie jest wykonywane, dopóki ToList
metoda nie zostanie wywołana. W związku z ToList
tym tylko metoda jest wykonywana asynchronicznie.
Details
W metodzie i metodach i Delete
HttpGet
Edit
metoda jest metodą, Find
która powoduje wysłanie zapytania do bazy danych, więc jest to metoda wykonywana asynchronicznie:
public async Task<ActionResult> Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Department department = await db.Departments.FindAsync(id);
if (department == null)
{
return HttpNotFound();
}
return View(department);
}
W metodach Create
, HttpPost Edit
i DeleteConfirmed
jest SaveChanges
to wywołanie metody, które powoduje wykonanie polecenia, a nie instrukcje, takie jak db.Departments.Add(department)
, które powodują modyfikację tylko jednostek w pamięci.
public async Task<ActionResult> Create(Department department)
{
if (ModelState.IsValid)
{
db.Departments.Add(department);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
Otwórz plik Views\Department\Index.cshtml i zastąp kod szablonu następującym kodem:
@model IEnumerable<ContosoUniversity.Models.Department>
@{
ViewBag.Title = "Departments";
}
<h2>Departments</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.Budget)
</th>
<th>
@Html.DisplayNameFor(model => model.StartDate)
</th>
<th>
Administrator
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Budget)
</td>
<td>
@Html.DisplayFor(modelItem => item.StartDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Administrator.FullName)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id=item.DepartmentID }) |
@Html.ActionLink("Details", "Details", new { id=item.DepartmentID }) |
@Html.ActionLink("Delete", "Delete", new { id=item.DepartmentID })
</td>
</tr>
}
</table>
Ten kod zmienia tytuł z Indeks na Działy, przenosi nazwę administratora po prawej stronie i udostępnia pełną nazwę administratora.
W widoku Tworzenie, Usuwanie, Szczegóły i Edytowanie zmień podpis pola InstructorID
na "Administrator" w taki sam sposób, jak zmieniono pole nazwy działu na "Dział" w widokach kursu.
W obszarze Tworzenie i edytowanie widoków użyj następującego kodu:
<label class="control-label col-md-2" for="InstructorID">Administrator</label>
W widokach Usuń i Szczegóły użyj następującego kodu:
<dt>
Administrator
</dt>
Uruchom aplikację i kliknij kartę Działy .
Wszystko działa tak samo jak w innych kontrolerach, ale w tym kontrolerze wszystkie zapytania SQL są wykonywane asynchronicznie.
Niektóre kwestie, które należy wziąć pod uwagę podczas korzystania z programowania asynchronicznego w programie Entity Framework:
- Kod asynchroniczny nie jest bezpieczny wątkiem. Innymi słowy, nie próbuj wykonywać wielu operacji równolegle przy użyciu tego samego wystąpienia kontekstu.
- Jeśli chcesz skorzystać z zalet wydajności kodu asynchronicznego, upewnij się, że wszystkie używane pakiety bibliotek (na przykład do stronicowania), należy również użyć asynchronicznego, jeśli wywołują dowolne metody programu Entity Framework, które powodują wysyłanie zapytań do bazy danych.
Korzystanie z procedur składowanych
Niektórzy deweloperzy i administratorzy baz danych wolą używać procedur składowanych na potrzeby dostępu do bazy danych. We wcześniejszych wersjach programu Entity Framework można pobrać dane przy użyciu procedury składowanej, wykonując nieprzetworzone zapytanie SQL, ale nie można poinstruować ef o użyciu procedur składowanych na potrzeby operacji aktualizacji. W programie EF 6 można łatwo skonfigurować funkcję Code First do korzystania z procedur składowanych.
W pliku DAL\SchoolContext.cs dodaj wyróżniony kod do
OnModelCreating
metody .protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); modelBuilder.Entity<Course>() .HasMany(c => c.Instructors).WithMany(i => i.Courses) .Map(t => t.MapLeftKey("CourseID") .MapRightKey("InstructorID") .ToTable("CourseInstructor")); modelBuilder.Entity<Department>().MapToStoredProcedures(); }
Ten kod instruuje program Entity Framework, aby używał procedur składowanych do operacji wstawiania, aktualizowania i usuwania w jednostce
Department
.W obszarze Konsola zarządzania pakietami wprowadź następujące polecenie:
add-migration DepartmentSP
Otwórz plik Migrations\<timestamp>_DepartmentSP.cs , aby wyświetlić kod w
Up
metodzie, która tworzy procedury składowane Insert, Update i Delete:public override void Up() { CreateStoredProcedure( "dbo.Department_Insert", p => new { Name = p.String(maxLength: 50), Budget = p.Decimal(precision: 19, scale: 4, storeType: "money"), StartDate = p.DateTime(), InstructorID = p.Int(), }, body: @"INSERT [dbo].[Department]([Name], [Budget], [StartDate], [InstructorID]) VALUES (@Name, @Budget, @StartDate, @InstructorID) DECLARE @DepartmentID int SELECT @DepartmentID = [DepartmentID] FROM [dbo].[Department] WHERE @@ROWCOUNT > 0 AND [DepartmentID] = scope_identity() SELECT t0.[DepartmentID] FROM [dbo].[Department] AS t0 WHERE @@ROWCOUNT > 0 AND t0.[DepartmentID] = @DepartmentID" ); CreateStoredProcedure( "dbo.Department_Update", p => new { DepartmentID = p.Int(), Name = p.String(maxLength: 50), Budget = p.Decimal(precision: 19, scale: 4, storeType: "money"), StartDate = p.DateTime(), InstructorID = p.Int(), }, body: @"UPDATE [dbo].[Department] SET [Name] = @Name, [Budget] = @Budget, [StartDate] = @StartDate, [InstructorID] = @InstructorID WHERE ([DepartmentID] = @DepartmentID)" ); CreateStoredProcedure( "dbo.Department_Delete", p => new { DepartmentID = p.Int(), }, body: @"DELETE [dbo].[Department] WHERE ([DepartmentID] = @DepartmentID)" ); }
W obszarze Konsola zarządzania pakietami wprowadź następujące polecenie:
update-database
Uruchom aplikację w trybie debugowania, kliknij kartę Działy , a następnie kliknij pozycję Utwórz nową.
Wprowadź dane dla nowego działu, a następnie kliknij przycisk Utwórz.
W programie Visual Studio przyjrzyj się dziennikom w oknie Dane wyjściowe , aby zobaczyć, że procedura składowana została użyta do wstawienia nowego wiersza Dział.
Code First tworzy domyślne nazwy procedur składowanej. Jeśli używasz istniejącej bazy danych, może być konieczne dostosowanie nazw procedur składowanych w celu użycia procedur składowanych zdefiniowanych już w bazie danych. Aby uzyskać informacje o tym, jak to zrobić, zobacz Entity Framework Code First Insert/Update/Delete Stored Procedures (Procedury składowane w programie Entity Framework Code First Insert/Update/Delete).
Jeśli chcesz dostosować wygenerowane procedury składowane, możesz edytować kod szkieletowy dla metody migracji Up
, która tworzy procedurę składowaną. Dzięki temu zmiany są odzwierciedlane za każdym razem, gdy migracja zostanie uruchomiona i zostanie zastosowana do produkcyjnej bazy danych, gdy migracje są uruchamiane automatycznie w środowisku produkcyjnym po wdrożeniu.
Jeśli chcesz zmienić istniejącą procedurę składowaną utworzoną w poprzedniej migracji, możesz użyć polecenia Add-Migration, aby wygenerować pustą migrację, a następnie ręcznie napisać kod, który wywołuje metodę AlterStoredProcedure .
Wdróż na platformie Azure
Ta sekcja wymaga ukończenia opcjonalnej sekcji Wdrażanie aplikacji na platformie Azure w samouczku Migracje i wdrażanie tej serii. Jeśli wystąpiły błędy migracji rozwiązane przez usunięcie bazy danych w projekcie lokalnym, pomiń tę sekcję.
W programie Visual Studio kliknij prawym przyciskiem myszy projekt w Eksplorator rozwiązań i wybierz polecenie Publikuj z menu kontekstowego.
Kliknij przycisk Opublikuj.
Program Visual Studio wdraża aplikację na platformie Azure, a aplikacja zostanie otwarta w domyślnej przeglądarce uruchomionej na platformie Azure.
Przetestuj aplikację, aby sprawdzić, czy działa.
Po pierwszym uruchomieniu strony, która uzyskuje dostęp do bazy danych, program Entity Framework uruchamia wszystkie metody migracji
Up
wymagane do zapewnienia aktualności bazy danych z bieżącym modelem danych. Teraz możesz używać wszystkich dodanych stron internetowych od czasu ostatniego wdrożenia, w tym stron działu dodanych w tym samouczku.
Uzyskiwanie kodu
Pobieranie ukończonego projektu
Dodatkowe zasoby
Linki do innych zasobów platformy Entity Framework 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:
- Informacje o kodzie asynchronicznym
- Tworzenie kontrolera działu
- Używane procedury składowane
- Wdrożone na platformie Azure
Przejdź do następnego artykułu, aby dowiedzieć się, jak obsługiwać konflikty, gdy wielu użytkowników aktualizuje tę samą jednostkę w tym samym czasie.
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla