Sdílet prostřednictvím


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 pracovat, 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 aplikaci znovu nasadíte do Azure spolu se všemi změnami databáze, které jste implementovali od prvního nasazení.

Následující ilustrace ukazují některé stránky, se kterými budete pracovat.

Stránka Oddělení

Vytvoření oddělení

V tomto kurzu se naučíte:

  • 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. V takovém případě nemůže server zpracovat nové požadavky, dokud se vlákna nevysadí. V synchronním kódu může být mnoho vláken svázané, 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 se jeho vlákno uvolní, aby server používal ke zpracování dalších požadavků. V důsledku toho asynchronní kód umožňuje efektivnější použití serverových prostředků a server je povolený pro zpracování většího provozu bez zpoždění.

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 obtížné ladění. V .NET 4.5 je psaní, testování a ladění asynchronního kódu mnohem jednodušší, abyste měli obecně psát asynchronní kód, pokud nemáte důvod ne. Asynchronní kód zavádí malou režii, ale u situací s nízkým provozem je dosažení výkonu 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í naleznete 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 předchozí kontrolery, s výjimkou této doby zaškrtněte políčko Použít asynchronní akce kontroleru.

Následující zvýraznění ukazuje, 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ět databázový dotaz Entity Framework:

  • Metoda je označena klíčovým slovem async , které kompilátoru říká, aby generoval zpětná volání pro části těla metody a automaticky vytvořit vrácený Task<ActionResult> objekt.
  • Návratový typ byl změněn z ActionResult na Task<ActionResult>. Typ Task<T> představuje probíhající práci s výsledkem typu T.
  • Klíčové await slovo se použilo na 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.
  • Byla volána asynchronní verze ToList metody rozšíření.

Proč se departments.ToList příkaz změnil, ale ne příkaz departments = db.Departments ? Důvodem je, že se asynchronně spustí pouze příkazy, které způsobují odesílání dotazů nebo příkazů do databáze. Příkaz departments = db.Departments nastaví dotaz, ale dotaz se nespustí, dokud ToList se metoda nevolá. Proto se provádí pouze ToList metoda asynchronně.

Details V metodě a Delete HttpGet Edit metodách je metoda ta, Find která způsobí odeslání dotazu do databáze, takže to je metoda, která se spustí 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);
}

V , CreateHttpPost Edita DeleteConfirmed metody, je SaveChanges volání metody, které způsobí spuštění příkazu, ne příkazy, jako db.Departments.Add(department) je například, které způsobují pouze entity v paměti být 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ý název správce.

V zobrazeníCh kurzů v zobrazeníCh kurzů změňte titulek InstructorID pole na "Správce", stejně jako jste změnili pole názvu 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 kontrolerech, ale v tomto kontroleru se všechny dotazy SQL spouští asynchronně.

Při používání asynchronního programování pomocí Entity Frameworku je potřeba mít na paměti některé věci:

  • Asynchronní kód není bezpečný pro přístup z více vláken. Jinými slovy, nepokoušejte se paralelně provádět více operací pomocí stejné instance kontextu.
  • Pokud chcete využít výhod 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í), použijte také asynchronní, pokud volají nějaké 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 raději používají uložené procedury pro přístup k databázi. V dřívějších verzích entity Framework můžete načíst data pomocí uložené procedury spuštěním nezpracovaného dotazu SQL, ale ef nemůže dát 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.

  1. V DAL\SchoolContext.cs přidejte do OnModelCreating metody zvýrazněný kód.

    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 Framework pokyn, aby pro operace Department vložení, aktualizace a odstranění entity používal uložené procedury.

  2. V konzole Správa balíčků zadejte následující příkaz:

    add-migration DepartmentSP

    Otevřete Migrations\<timestamp>_DepartmentSP.cs zobrazte kód v Up metodě, která vytvoří 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)"
        );    
    }
    
  3. V konzole Správa balíčků zadejte následující příkaz:

    update-database

  4. Spusťte aplikaci v režimu ladění, klikněte na kartu Oddělení a potom klikněte na vytvořit nový.

  5. Zadejte data pro nové oddělení a potom klikněte na Vytvořit.

  6. V sadě Visual Studio se podívejte na protokoly v okně Výstup a podívejte se, že se k vložení nového řádku Oddělení použila uložená procedura.

    Oddělení – vložit sp

Code First vytvoří výchozí názvy uložených procedur. Pokud používáte existující databázi, možná budete muset upravit názvy uložených procedur, aby bylo možné použít uložené procedury, které už jsou v databázi definované. Informace o tom, jak to provést, naleznete v tématu Entity Framework Code First Insert/Update/Delete Uložené procedury.

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 pro produkční databázi při automatickém spuštění migrace v produkčním prostředí po nasazení.

Pokud chcete změnit existující uloženou proceduru vytvořenou v předchozí migraci, můžete pomocí příkazu Add-Migration vygenerovat prázdnou migraci a pak 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.

  1. V sadě Visual Studio klikněte pravým tlačítkem myši na projekt v Průzkumník řešení a v místní nabídce vyberte Publikovat.

  2. Klikněte na Publikovat.

    Visual Studio nasadí aplikaci do Azure a aplikace se otevře ve výchozím prohlížeči spuštěném v Azure.

  3. Otestujte aplikaci a ověřte, že funguje.

    Při prvním spuštění stránky, která přistupuje k databázi, spustí Entity Framework všechny metody migrace Up potřebné k tomu, aby byla databáze 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

Stažení dokončeného projektu

Další materiály

Odkazy na další prostředky Entity Framework najdete v ASP.NET přístupu k datům – doporučené zdroje informací.

Další kroky

V tomto kurzu se naučíte:

  • Dozvěděli jste se o asynchronním kódu
  • 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 současně.