Kurz: Použití asynchronních a uložených procedur s EF v aplikaci ASP.NET MVC
V předchozích kurzech jste se naučili číst a aktualizovat data pomocí synchronního programovacího modelu. V tomto kurzu se dozvíte, jak implementovat asynchronní programovací model. Asynchronní kód může aplikaci pomoct lépe fungovat, protože lépe využívá prostředky serveru.
V tomto kurzu se také dozvíte, jak používat uložené procedury pro operace vložení, aktualizace a odstranění entity.
Nakonec znovu nasadíte aplikaci do Azure spolu se všemi změnami databáze, které jste implementovali od prvního nasazení.
Následující ilustrace znázorňují některé ze stránek, se kterými budete pracovat.
V tomto kurzu jste:
- Informace o asynchronním kódu
- Vytvoření kontroleru oddělení
- Použití uložených procedur
- Nasazení do Azure
Požadavky
Proč používat asynchronní kód
Webový server má k dispozici omezený počet vláken a v situacích s vysokým zatížením se můžou používat všechna dostupná vlákna. Když k tomu dojde, nemůže server zpracovávat nové požadavky, dokud se vlákna neuvolní. U synchronního kódu může být mnoho vláken svázaných, zatímco ve skutečnosti neprovádí žádnou práci, protože čekají na dokončení vstupně-výstupních operací. Když proces čeká na dokončení vstupně-výstupních operací v asynchronním kódu, uvolní se jeho vlákno, aby ho server použil ke zpracování dalších požadavků. V důsledku toho asynchronní kód umožňuje efektivněji používat prostředky serveru a server může bez zpoždění zpracovávat více přenosů.
V dřívějších verzích rozhraní .NET bylo psaní a testování asynchronního kódu složité, náchylné k chybám a bylo obtížné ladit. V .NET 4.5 je psaní, testování a ladění asynchronního kódu mnohem jednodušší, že byste obecně měli psát asynchronní kód, pokud nemáte důvod ne. Asynchronní kód přináší malou režii, ale v situacích s nízkým provozem je výkonový zásah zanedbatelný, zatímco v situacích s vysokým provozem je potenciální zlepšení výkonu podstatné.
Další informace o asynchronním programování najdete v tématu Použití asynchronní podpory rozhraní .NET 4.5 k zabránění blokování volání.
Vytvoření kontroleru oddělení
Vytvořte kontroler oddělení stejným způsobem jako u předchozích kontrolerů, ale tentokrát zaškrtněte políčko Použít akce asynchronního kontroleru .
Následující zvýraznění ukazují, co bylo přidáno do synchronního kódu pro metodu Index
, aby byla asynchronní:
public async Task<ActionResult> Index()
{
var departments = db.Departments.Include(d => d.Administrator);
return View(await departments.ToListAsync());
}
Byly použity čtyři změny, které umožňují asynchronní spouštění dotazů na databázi Entity Framework:
- Metoda je označena klíčovým slovem
async
, které kompilátoru říká, aby vygeneroval zpětná volání pro části těla metody a automaticky vytvořil vrácenýTask<ActionResult>
objekt. - Návratový typ se změnil z
ActionResult
naTask<ActionResult>
. TypTask<T>
představuje probíhající práci s výsledkem typuT
. - Klíčové
await
slovo se použilo pro volání webové služby. Když kompilátor uvidí toto klíčové slovo, na pozadí rozdělí metodu na dvě části. První část končí operací, která se spouští asynchronně. Druhá část je vložena do metody zpětného volání, která je volána po dokončení operace. - Asynchronní verze
ToList
rozšiřující metody byla volána.
Proč se departments.ToList
příkaz změnil, ale ne příkaz?departments = db.Departments
Důvodem je, že pouze příkazy, které způsobují odesílání dotazů nebo příkazů do databáze, jsou spouštěny asynchronně. Příkaz departments = db.Departments
nastaví dotaz, ale dotaz se nespustí, dokud ToList
není volána metoda. Proto je ToList
pouze metoda spuštěna asynchronně.
Details
V metodě aEdit
HttpGet
metodách a metodách a Delete
je metoda ta, Find
která způsobí odeslání dotazu do databáze, takže je to metoda, která se spouští asynchronně:
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);
}
Create
V metodách , HttpPost Edit
a DeleteConfirmed
je SaveChanges
to volání metody, které způsobuje spuštění příkazu, nikoli příkazy, jako db.Departments.Add(department)
jsou, které způsobují pouze entity v paměti, aby byly změněny.
public async Task<ActionResult> Create(Department department)
{
if (ModelState.IsValid)
{
db.Departments.Add(department);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
Otevřete Views\Department\Index.cshtml a nahraďte kód šablony následujícím kódem:
@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>
Tento kód změní název z indexu na Oddělení, přesune jméno správce doprava a poskytne úplné jméno správce.
V zobrazeníCh Vytvořit, Odstranit, Podrobnosti a Upravit změňte popis pro InstructorID
pole na Správce stejným způsobem, jakým jste v zobrazeních kurzu změnili pole s názvem oddělení na Oddělení.
V zobrazení Vytvořit a Upravit použijte následující kód:
<label class="control-label col-md-2" for="InstructorID">Administrator</label>
V zobrazení Odstranit a Podrobnosti použijte následující kód:
<dt>
Administrator
</dt>
Spusťte aplikaci a klikněte na kartu Oddělení .
Všechno funguje stejně jako v ostatních řadičích, ale v tomto kontroleru se všechny dotazy SQL spouští asynchronně.
Při používání asynchronního programování v Entity Frameworku je potřeba mít na paměti několik věcí:
- Asynchronní kód není bezpečný z více vláken. Jinými slovy, nepokoušejte se provádět více operací paralelně pomocí stejné instance kontextu.
- Pokud chcete využívat výhody výkonu asynchronního kódu, ujistěte se, že všechny balíčky knihovny, které používáte (například pro stránkování), také použijte asynchronní, pokud volají metody Entity Framework, které způsobují odesílání dotazů do databáze.
Použití uložených procedur
Někteří vývojáři a dbaři dávají přednost používání uložených procedur pro přístup k databázi. V dřívějších verzích Entity Frameworku můžete načíst data pomocí uložené procedury spuštěním nezpracovaného dotazu SQL, ale nemůžete dát EF pokyn, aby pro operace aktualizace používal uložené procedury. V EF 6 je snadné nakonfigurovat Code First pro použití uložených procedur.
V souboru DAL\SchoolContext.cs přidejte zvýrazněný kód 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(); }
Tento kód dává Entity Frameworku pokyn k použití uložených procedur pro operace
Department
vložení, aktualizace a odstranění entity.V části Konzola pro správu balíčků zadejte následující příkaz:
add-migration DepartmentSP
Otevřete soubor Migrations\<timestamp>_DepartmentSP.cs a zobrazte kód v
Up
metodě, která vytváří uložené procedury Insert, Update a 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)" ); }
V části Konzola pro správu balíčků zadejte následující příkaz:
update-database
Spusťte aplikaci v režimu ladění, klikněte na kartu Oddělení a pak klikněte na Vytvořit novou.
Zadejte data pro nové oddělení a klikněte na Vytvořit.
V sadě Visual Studio se podívejte na protokoly v okně Výstup a zjistěte, že se k vložení nového řádku Oddělení použila uložená procedura.
Code First vytvoří výchozí názvy uložených procedur. Pokud používáte existující databázi, možná budete muset přizpůsobit názvy uložených procedur, aby bylo možné používat uložené procedury, které jsou v databázi už definované. Informace o tom, jak to provést, najdete v tématu Entity Framework Code First Insert/Update/Delete Stored Procedures.
Pokud chcete přizpůsobit, co vygenerované uložené procedury dělají, můžete upravit vygenerovaný Up
kód pro metodu migrace, která vytvoří uloženou proceduru. Změny se tak projeví při každém spuštění migrace a použijí se na produkční databázi, když se migrace po nasazení automaticky spustí v produkčním prostředí.
Pokud chcete změnit existující uloženou proceduru vytvořenou při předchozí migraci, můžete pomocí příkazu Add-Migration vygenerovat prázdnou migraci a ručně napsat kód, který volá metodu AlterStoredProcedure .
Nasazení do Azure
Tato část vyžaduje, abyste dokončili volitelnou část Nasazení aplikace do Azure v kurzu Migrace a nasazení této série. Pokud došlo k chybám migrace, které jste vyřešili odstraněním databáze v místním projektu, přeskočte tuto část.
V sadě Visual Studio klikněte pravým tlačítkem na projekt v Průzkumník řešení a v místní nabídce vyberte Publikovat.
Klikněte na Publikovat.
Visual Studio nasadí aplikaci do Azure a aplikace se otevře ve výchozím prohlížeči, který běží v Azure.
Otestujte aplikaci a ověřte, že funguje.
Při prvním spuštění stránky, která přistupuje k databázi, Entity Framework spustí všechny metody migrace
Up
potřebné k tomu, aby databáze byla aktuální s aktuálním datovým modelem. Teď můžete použít všechny webové stránky, které jste přidali od posledního nasazení, včetně stránek oddělení, které jste přidali v tomto kurzu.
Získání kódu
Další materiály
Odkazy na další prostředky Entity Frameworku najdete v tématu ASP.NET Přístup k datům – doporučené zdroje.
Další kroky
V tomto kurzu jste:
- Seznámení s asynchronním kódem
- Vytvoření kontroleru oddělení
- Použité uložené procedury
- Nasazeno do Azure
V dalším článku se dozvíte, jak řešit konflikty, když více uživatelů aktualizuje stejnou entitu najednou.
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro