Sdílet prostřednictvím


Použití Entity Framework 4.0 a ObjectDataSource Ovládací prvek, Část 1: Začínáme

Tom Dykstra

Tato série kurzů vychází z webové aplikace Contoso University vytvořené Začínáme s řadou kurzů Entity Framework 4.0. Pokud jste nedokončí předchozí kurzy, můžete si jako výchozí bod pro tento kurz stáhnout aplikaci , kterou jste vytvořili. Můžete si také stáhnout aplikaci vytvořenou kompletní řadou kurzů.

Ukázková webová aplikace Contoso University ukazuje, jak vytvářet ASP.NET Web Forms aplikace pomocí entity frameworku 4.0 a sady Visual Studio 2010. Ukázková aplikace je web fiktivní univerzity Contoso. Zahrnuje funkce, jako je přijetí studentů, vytváření kurzů a zadání instruktora.

Tento kurz ukazuje příklady v jazyce C#. Ukázka ke stažení obsahuje kód v jazyce C# i Visual Basic.

První databáze

S daty v Entity Frameworku můžete pracovat třemi způsoby: Database First, Model First a Code First. Tento kurz je určený pro Database First. Informace o rozdílech mezi těmito pracovními postupy a pokyny k výběru nejvhodnějšího pracovního postupu pro váš scénář najdete v tématu Pracovní postupy vývoje entity frameworku.

webové formuláře

Stejně jako řada Začínáme i tato série kurzů používá model ASP.NET Web Forms a předpokládá, že víte, jak pracovat s ASP.NET Web Forms v sadě Visual Studio. Pokud ne, podívejte se na Začínáme s ASP.NET 4.5 Web Forms. Pokud dáváte přednost práci s architekturou ASP.NET MVC, projděte si téma Začínáme s rozhraním Entity Framework pomocí ASP.NET MVC.

Verze softwaru

Zobrazeno v kurzu Funguje také s
Windows 7 Windows 8
Visual Studio 2010 Visual Studio 2010 Express pro web. Kurz nebyl testován s novějšími verzemi sady Visual Studio. Výběry nabídek, dialogová okna a šablony jsou různé.
.NET 4 .NET 4.5 je zpětně kompatibilní s .NET 4, ale kurz nebyl testován s .NET 4.5.
Entity Framework 4 Kurz nebyl testován s novějšími verzemi Entity Frameworku. Počínaje Entity Framework 5 používá EF ve výchozím nastavení ten DbContext API , který byl zaveden s EF 4.1. Ovládací prvek EntityDataSource byl navržen tak, aby používal ObjectContext rozhraní API. Informace o použití ovládacího prvku EntityDataSource s rozhraním API najdete v DbContexttomto blogovém příspěvku.

Dotazy

Pokud máte otázky, které přímo nesouvisejí s kurzem, můžete je publikovat na fóru ASP.NET Entity Framework, na fóru Entity Framework a LINQ to Entities nebo na StackOverflow.com.

Ovládací EntityDataSource prvek umožňuje velmi rychle vytvořit aplikaci, ale obvykle vyžaduje, abyste na stránkách .aspx zachovali značné množství obchodní logiky a logiky přístupu k datům. Pokud očekáváte, že se vaše aplikace zvětšuje ve složitosti a bude vyžadovat průběžnou údržbu, můžete předem investovat více času na vývoj, abyste vytvořili vícevrstvé nebo vrstvené aplikační struktury, které budou lépe udržovatelné. K implementaci této architektury oddělíte prezentační vrstvu od vrstvy obchodní logiky (BLL) a vrstvy přístupu k datům (DAL). Jedním ze způsobů, jak tuto strukturu implementovat, je použít ObjectDataSource ovládací prvek místo EntityDataSource ovládacího prvku. Při použití ObjectDataSource ovládacího prvku implementujete vlastní kód pro přístup k datům a pak ho vyvoláte na stránkách .aspx pomocí ovládacího prvku, který má mnoho stejných funkcí jako jiné ovládací prvky zdroje dat. To vám umožní zkombinovat výhody n-vrstvého přístupu s výhodami použití Web Forms řízení přístupu k datům.

Ovládací ObjectDataSource prvek poskytuje větší flexibilitu i v jiných ohledech. Vzhledem k tomu, že píšete vlastní kód pro přístup k datům, je jednodušší udělat víc než jen číst, vkládat, aktualizovat nebo odstraňovat konkrétní typ entity, což jsou úlohy, ke kterým EntityDataSource je ovládací prvek navržen. Můžete například provádět protokolování při každé aktualizaci entity, archivovat data při každém odstranění entity nebo automaticky kontrolovat a aktualizovat související data podle potřeby při vkládání řádku s hodnotou cizího klíče.

Třídy obchodní logiky a úložiště

Ovládací ObjectDataSource prvek funguje tak, že vyvolá třídu, kterou vytvoříte. Třída zahrnuje metody, které načítají a aktualizují data, a názvy těchto metod zadáte ovládacímu ObjectDataSource prvku ve značkách. Během vykreslování nebo zpětného ObjectDataSource zpracování volá metody, které jste zadali.

Kromě základních operací CRUD může třída, kterou vytvoříte pro použití s ovládacím ObjectDataSource prvku, potřebovat ke spuštění obchodní logiky při ObjectDataSource čtení nebo aktualizaci dat. Když například aktualizujete oddělení, budete muset ověřit, že žádné jiné oddělení nemají stejného správce, protože jedna osoba nemůže být správcem více než jednoho oddělení.

V některých ObjectDataSource dokumentech, jako je například ObjectDataSource – přehled třídy, volá ovládací prvek třídu označovanou jako obchodní objekt , který zahrnuje obchodní logiku i logiku přístupu k datům. V tomto kurzu vytvoříte samostatné třídy pro obchodní logiku a logiku přístupu k datům. Třída, která zapouzdřuje logiku přístupu k datům, se nazývá úložiště. Třída obchodní logiky zahrnuje metody obchodní logiky i metody přístupu k datům, ale metody přístupu k datům volají úložiště, aby prováděly úlohy přístupu k datům.

Vytvoříte také abstraktní vrstvu mezi BLL a DAL, která usnadňuje automatizované testování jednotek BLL. Tato vrstva abstrakce se implementuje vytvořením rozhraní a použitím rozhraní při vytváření instance úložiště ve třídě obchodní logiky. To vám umožní poskytnout třídu obchodní logiky s odkazem na jakýkoli objekt, který implementuje rozhraní úložiště. Pro normální provoz zadáte objekt úložiště, který funguje s rozhraním Entity Framework. Pro účely testování poskytnete objekt úložiště, který pracuje s daty uloženými způsobem, se kterým můžete snadno manipulovat, například s proměnnými tříd definovanými jako kolekce.

Následující obrázek znázorňuje rozdíl mezi třídou obchodní logiky, která zahrnuje logiku přístupu k datům bez úložiště, a třídou, která používá úložiště.

Obrázek05

Začnete vytvořením webových stránek, na kterých ObjectDataSource je ovládací prvek vázán přímo na úložiště, protože provádí pouze základní úlohy přístupu k datům. V dalším kurzu vytvoříte třídu obchodní logiky s logikou ověřování a svážete ObjectDataSource ovládací prvek s danou třídou místo s třídou úložiště. Vytvoříte také testy jednotek pro logiku ověřování. Ve třetím kurzu v této sérii přidáte do aplikace funkci řazení a filtrování.

Stránky, které vytvoříte v tomto kurzu, pracují se Departments sadou entit datového modelu, který jste vytvořili v sérii kurzů Začínáme.

Snímek obrazovky, který ukazuje, jak by měla vaše stránka Oddělení vypadat.

Obrázek02

Aktualizace databáze a datového modelu

Tento kurz zahájíte provedením dvou změn v databázi, které vyžadují odpovídající změny datového modelu, který jste vytvořili v Začínáme s Entity Framework a Web Forms kurzy. V jednom z těchto kurzů jste provedli změny v návrháři ručně, abyste po změně databáze synchronizovali datový model s databází. V tomto kurzu použijete nástroj Aktualizovat model z databáze od návrháře k automatické aktualizaci datového modelu.

Přidání relace do databáze

V sadě Visual Studio otevřete webovou aplikaci Contoso University, kterou jste vytvořili v Začínáme s řadou kurzů Entity Framework a Web Forms, a pak otevřete SchoolDiagram diagram databáze.

Když se podíváte na Department tabulku v diagramu databáze, uvidíte, že obsahuje Administrator sloupec. Tento sloupec je cizím klíčem tabulky Person , ale v databázi není definován žádný vztah cizího klíče. Musíte vytvořit relaci a aktualizovat datový model tak, aby Entity Framework mohl tuto relaci automaticky zpracovat.

V diagramu databáze klikněte pravým tlačítkem na Department tabulku a vyberte Relace.

Obrázek80

V poli Relace cizího klíče klikněte na Přidat a potom klikněte na tři tečky pro Tabulky a sloupce Specifikace.

Obrázek81

V dialogovém okně Tabulky a sloupce nastavte tabulku a pole primárního klíče na Person a PersonIDa nastavte tabulku a pole cizího klíče na Department a Administrator. (Když to uděláte, název relace se změní z FK_Department_Department na FK_Department_Person.)

Obrázek82

Klikněte na OK v poli Tabulky a sloupce, v poli Relace cizího klíče klikněte na Zavřít a uložte změny. Pokud se zobrazí dotaz, jestli chcete tabulky a Department uložitPerson, klikněte na Ano.

Poznámka

Pokud jste odstranili Person řádky, které odpovídají datům, která už jsou ve sloupci Administrator , nebudete moct tuto změnu uložit. V takovém případě použijte editor tabulek v Průzkumníku serveru a ujistěte se, že Administrator hodnota v každém Department řádku obsahuje ID záznamu Person , který v tabulce skutečně existuje.

Po uložení změny nebudete moct odstranit řádek z Person tabulky, pokud je tato osoba správcem oddělení. V produkční aplikaci byste zadali konkrétní chybovou zprávu, když omezení databáze brání odstranění, nebo byste zadali kaskádové odstranění. Příklad určení kaskádového odstranění najdete v tématu Entity Framework a ASP.NET – Začínáme část 2.

Přidání zobrazení do databáze

Na nové stránce Departments.aspx , kterou budete vytvářet, chcete zadat rozevírací seznam instruktorů se jmény ve formátu "příjmení, první", aby uživatelé mohli vybrat správce oddělení. Abyste to usnadnili, vytvoříte v databázi zobrazení. Zobrazení se bude skládat jenom z dat potřebných v rozevíracím seznamu: celého jména (správně naformátovaného) a klíče záznamu.

V Průzkumníku serveru rozbalte School.mdf, klikněte pravým tlačítkem na složku Zobrazení a vyberte Přidat nové zobrazení.

Obrázek06

Po zobrazení dialogového okna Přidat tabulku klikněte na Zavřít a vložte do podokna SQL následující příkaz SQL:

SELECT        LastName + ',' + FirstName AS FullName, PersonID
FROM          dbo.Person
WHERE        (HireDate IS NOT NULL)

Uložte zobrazení jako vInstructorName.

Aktualizace datového modelu

Ve složce DAL otevřete soubor SchoolModel.edmx , klikněte pravým tlačítkem na návrhovou plochu a vyberte Aktualizovat model z databáze.

Obrázek07

V dialogovém okně Zvolte databázové objekty vyberte kartu Přidat a vyberte zobrazení, které jste právě vytvořili.

Obrázek08

Klikněte na Finish (Dokončit).

V návrháři vidíte, že nástroj vytvořil entitu vInstructorName a nové přidružení mezi Department entitami a Person .

Obrázek 13

Poznámka

V oknech Výstup a Seznam chyb se může zobrazit zpráva s upozorněním, že nástroj automaticky vytvořil primární klíč pro nové vInstructorName zobrazení. Toto chování je očekávané.

Když odkazujete na novou vInstructorName entitu v kódu, nechcete používat konvenci databáze, která předponuje malé písmeno "v". Proto entitu a sadu entit v modelu přejmenujete.

Otevřete Prohlížeč modelů. Zobrazí se vInstructorName jako typ entity a zobrazení.

Obrázek 14

V části SchoolModel (ne SchoolModel.Store) klikněte pravým tlačítkem na vInstructorName a vyberte Vlastnosti. V okně Vlastnosti změňte vlastnost Name na InstructorName a změňte vlastnost Název sady entit na InstructorNames.

Obrázek 15

Uložte a zavřete datový model a pak projekt znovu sestavte.

Použití třídy úložiště a ovládacího prvku ObjectDataSource

Ve složce DAL vytvořte nový soubor třídy, pojmenujte ho SchoolRepository.cs a nahraďte stávající kód následujícím kódem:

using System;
using System.Collections.Generic;
using System.Linq;
using ContosoUniversity.DAL;

namespace ContosoUniversity.DAL
{
    public class SchoolRepository : IDisposable
    {
        private SchoolEntities context = new SchoolEntities();

        public IEnumerable<Department> GetDepartments()
        {
            return context.Departments.Include("Person").ToList();
        }

        private bool disposedValue = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposedValue)
            {
                if (disposing)
                {
                    context.Dispose();
                }
            }
            this.disposedValue = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

    }
}

Tento kód poskytuje jednu GetDepartments metodu, která vrací všechny entity v Departments sadě entit. Protože víte, že budete přistupovat k Person navigační vlastnosti pro každý vrácený řádek, určíte dychtivé načítání pro tuto vlastnost pomocí Include metody . Třída také implementuje IDisposable rozhraní, aby se zajistilo, že připojení k databázi je uvolněno při odstranění objektu.

Poznámka

Běžným postupem je vytvořit třídu úložiště pro každý typ entity. V tomto kurzu se používá jedna třída úložiště pro více typů entit. Další informace o vzoru úložiště najdete v příspěvcích na blogu týmu Entity Framework a v blogu Julie Lermanové.

Metoda GetDepartments vrací IEnumerable objekt místo objektu IQueryable , aby se zajistilo, že vrácená kolekce je použitelná i po odstranění samotného objektu úložiště. Objekt IQueryable může způsobit přístup k databázi při každém přístupu, ale objekt úložiště může být odstraněn v době, kdy se ovládací prvek příchozích dat pokusí data vykreslit. Můžete vrátit jiný typ kolekce, například IList objekt místo objektu IEnumerable . Vrácení objektu IEnumerable však zajistí, že můžete provádět typické úlohy zpracování seznamu jen pro čtení, jako foreach jsou smyčky a dotazy LINQ, ale nemůžete přidávat nebo odebírat položky v kolekci, což může znamenat, že takové změny budou zachovány v databázi.

Vytvořte stránku Departments.aspx, která používá stránku site.master, a přidejte do ovládacího prvku s názvem Content2následující kód Content :

<h2>Departments</h2>
    <asp:ObjectDataSource ID="DepartmentsObjectDataSource" runat="server" 
        TypeName="ContosoUniversity.DAL.SchoolRepository" 
        DataObjectTypeName="ContosoUniversity.DAL.Department" 
        SelectMethod="GetDepartments" >
    </asp:ObjectDataSource>
    <asp:GridView ID="DepartmentsGridView" runat="server" AutoGenerateColumns="False"
        DataSourceID="DepartmentsObjectDataSource"  >
        <Columns>
            <asp:CommandField ShowEditButton="True" ShowDeleteButton="True"
                ItemStyle-VerticalAlign="Top">
            </asp:CommandField>
            <asp:DynamicField DataField="Name" HeaderText="Name" SortExpression="Name" ItemStyle-VerticalAlign="Top" />
            <asp:DynamicField DataField="Budget" HeaderText="Budget" SortExpression="Budget" ItemStyle-VerticalAlign="Top" />
            <asp:DynamicField DataField="StartDate" HeaderText="Start Date" ItemStyle-VerticalAlign="Top" />
            <asp:TemplateField HeaderText="Administrator" SortExpression="Person.LastName" ItemStyle-VerticalAlign="Top" >
                <ItemTemplate>
                    <asp:Label ID="AdministratorLastNameLabel" runat="server" Text='<%# Eval("Person.LastName") %>'></asp:Label>,
                    <asp:Label ID="AdministratorFirstNameLabel" runat="server" Text='<%# Eval("Person.FirstMidName") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

Tento kód vytvoří ovládací prvek ObjectDataSource , který používá třídu úložiště, kterou jste právě vytvořili, a GridView ovládací prvek k zobrazení dat. Ovládací GridView prvek určuje příkazy Upravit a Odstranit , ale ještě jste nepřidali kód pro jejich podporu.

Několik sloupců používá DynamicField ovládací prvky, abyste mohli využít výhod automatického formátování a funkce ověřování dat. Aby tyto funkce fungovaly, budete muset volat metodu EnableDynamicData v obslužné rutině Page_Init události. (DynamicControl Ovládací prvky se v Administrator poli nepoužívají, protože nefungují s navigačními vlastnostmi.)

Atributy Vertical-Align="Top" se stanou důležitými později, když do mřížky přidáte sloupec s vnořeným GridView ovládacím prvkem.

Otevřete soubor Departments.aspx.cs a přidejte následující using příkaz:

using ContosoUniversity.DAL;

Pak přidejte následující obslužnou rutinu pro událost stránky Init :

protected void Page_Init(object sender, EventArgs e)
{
    DepartmentsGridView.EnableDynamicData(typeof(Department));
}

Ve složce DAL vytvořte nový soubor třídy s názvem Department.cs a nahraďte stávající kód následujícím kódem:

using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace ContosoUniversity.DAL
{
    [MetadataType(typeof(DepartmentMetaData))]
    public partial class Department
    {
    }

    public class DepartmentMetaData
    {
        [DataType(DataType.Currency)]
        [Range(0, 1000000, ErrorMessage = "Budget must be less than $1,000,000.00")]
        public Decimal Budget { get; set; }

        [DisplayFormat(DataFormatString="{0:d}",ApplyFormatInEditMode=true)]
        public DateTime StartDate { get; set; }

    }
}

Tento kód přidá metadata do datového modelu. Určuje, že Budget vlastnost Department entity ve skutečnosti představuje měnu, i když její datový typ je Decimal, a určuje, že hodnota musí být mezi 0 a 1 000 000,00 USD. Určuje také, že StartDate vlastnost by měla být formátována jako datum ve formátu mm/dd/rrrr.

Spusťte stránku Departments.aspx .

Snímek obrazovky, který zobrazuje stránku Oddělení, když byla spuštěna.

Všimněte si, že i když jste v kódu stránky Departments.aspx pro sloupce Rozpočet nebo Počáteční datum nezadali formátovací řetězec, ovládací prvky na ně DynamicField použily výchozí formátování měny a data pomocí metadat, která jste zadali v souboru Department.cs .

Přidání funkcí vložení a odstranění

Otevřete SchoolRepository.cs a přidejte následující kód, abyste vytvořili metodu Insert a metodu Delete . Kód také obsahuje metodu s názvem GenerateDepartmentID , která vypočítá další dostupnou hodnotu klíče záznamu pro použití metodou Insert . To je povinné, protože databáze není nakonfigurovaná tak, aby tuto hodnotu automaticky vypočítala Department pro tabulku.

public void InsertDepartment(Department department)
{
    try
    {
        department.DepartmentID = GenerateDepartmentID();
        context.Departments.AddObject(department);
        context.SaveChanges();
    }
    catch (Exception ex)
    {
        //Include catch blocks for specific exceptions first,
        //and handle or log the error as appropriate in each.
        //Include a generic catch block like this one last.
        throw ex;
    }
}

public void DeleteDepartment(Department department)
{
    try
    {
        context.Departments.Attach(department);
        context.Departments.DeleteObject(department);
        context.SaveChanges();
    }
    catch (Exception ex)
    {
        //Include catch blocks for specific exceptions first,
        //and handle or log the error as appropriate in each.
        //Include a generic catch block like this one last.
        throw ex;
    }
}

private Int32 GenerateDepartmentID()
{
    Int32 maxDepartmentID = 0;
    var department = (from d in GetDepartments()
                      orderby d.DepartmentID descending
                      select d).FirstOrDefault();
    if (department != null)
    {
        maxDepartmentID = department.DepartmentID + 1;
    }
    return maxDepartmentID;
}

Metoda Attach

Metoda DeleteDepartment volá metodu Attach za účelem opětovného vytvoření propojení, které je udržováno ve správci stavu objektu kontextu objektu mezi entitou v paměti a databázovým řádkem, který představuje. K tomu musí dojít dříve, než metoda zavolá metodu SaveChanges .

Termín kontext objektu odkazuje na třídu Entity Framework, která je odvozena od ObjectContext třídy, kterou používáte pro přístup k vašim sadám entit a entitám. V kódu pro tento projekt má třída název SchoolEntitiesa instance je vždy pojmenována context. Správce stavu objektu kontextu objektu je třída, která je odvozena od ObjectStateManager třídy. Kontakt objektu používá správce stavu objektu k ukládání objektů entit a ke sledování toho, jestli je každý z nich synchronizovaný s odpovídajícím řádkem tabulky nebo řádky v databázi.

Když čtetete entitu, kontext objektu ji uloží do správce stavu objektu a sleduje, jestli je tato reprezentace objektu synchronizovaná s databází. Pokud například změníte hodnotu vlastnosti, nastaví se příznak, který označuje, že vlastnost, kterou jste změnili, už není synchronizovaná s databází. Když pak zavoláte metodu SaveChanges , kontext objektu ví, co dělat v databázi, protože správce stavu objektu přesně ví, co se liší mezi aktuálním stavem entity a stavem databáze.

Tento proces však obvykle nefunguje ve webové aplikaci, protože instance kontextu objektu, která čte entitu, spolu se vším v jejím správci stavu objektu, je odstraněna po vykreslení stránky. Instance kontextu objektu, která musí použít změny, je nová instance, která je vytvořena pro následné zpracování. V případě DeleteDepartment metody ObjectDataSource ovládací prvek znovu vytvoří původní verzi entity z hodnot ve stavu zobrazení, ale tato znovu vytvořená Department entita neexistuje ve správci stavu objektů. Pokud jste volali metodu DeleteObject pro tuto znovu vytvořenou entitu, volání by selhalo, protože kontext objektu neví, jestli je entita synchronizovaná s databází. Volání Attach metody však znovu vytvoří stejné sledování mezi znovu vytvořenou entitou a hodnotami v databázi, které bylo původně provedeno automaticky při čtení entity v dřívější instanci kontextu objektu.

Existují chvíle, kdy nechcete, aby kontext objektu sledoval entity ve správci stavu objektů, a můžete nastavit příznaky, které mu v tom zabrání. Příklady jsou uvedeny v dalších kurzech v této sérii.

The SaveChanges – metoda

Tato jednoduchá třída úložiště znázorňuje základní principy provádění operací CRUD. V tomto příkladu SaveChanges je metoda volána ihned po každé aktualizaci. V produkční aplikaci můžete chtít volat metodu SaveChanges ze samostatné metody, abyste měli větší kontrolu nad tím, kdy se databáze aktualizuje. (Na konci dalšího kurzu najdete odkaz na dokument white paper, který popisuje vzor jednotek práce, což je jeden z přístupů ke koordinaci souvisejících aktualizací.) Všimněte si také, že v příkladu DeleteDepartment metoda neobsahuje kód pro zpracování konfliktů souběžnosti; kód, který bude přidán v pozdějším kurzu v této sérii.

Načítání jmen instruktorů, které se mají vybrat při vkládání

Uživatelé musí mít možnost vybrat správce ze seznamu instruktorů v rozevíracím seznamu při vytváření nových oddělení. Proto do souboru SchoolRepository.cs přidejte následující kód, který vytvoří metodu pro načtení seznamu instruktorů pomocí zobrazení, které jste vytvořili dříve:

public IEnumerable<InstructorName> GetInstructorNames()
{
    return context.InstructorNames.OrderBy("it.FullName").ToList();
}

Vytvoření stránky pro vkládání oddělení

Vytvořte stránku DepartmentsAdd.aspx , která používá stránku Site.Master , a přidejte následující kód do Content ovládacího prvku s názvem Content2:

<h2>Departments</h2>
    <asp:ObjectDataSource ID="DepartmentsObjectDataSource" runat="server" 
        TypeName="ContosoUniversity.DAL.SchoolRepository" DataObjectTypeName="ContosoUniversity.DAL.Department"
        InsertMethod="InsertDepartment" >
    </asp:ObjectDataSource>
    <asp:DetailsView ID="DepartmentsDetailsView" runat="server" 
        DataSourceID="DepartmentsObjectDataSource" AutoGenerateRows="False"
        DefaultMode="Insert" OnItemInserting="DepartmentsDetailsView_ItemInserting">
        <Fields>
            <asp:DynamicField DataField="Name" HeaderText="Name" />
            <asp:DynamicField DataField="Budget" HeaderText="Budget" />
            <asp:DynamicField DataField="StartDate" HeaderText="Start Date" />
            <asp:TemplateField HeaderText="Administrator">
                <InsertItemTemplate>
                    <asp:ObjectDataSource ID="InstructorsObjectDataSource" runat="server" 
                        TypeName="ContosoUniversity.DAL.SchoolRepository" 
                        DataObjectTypeName="ContosoUniversity.DAL.InstructorName"
                        SelectMethod="GetInstructorNames" >
                    </asp:ObjectDataSource>
                    <asp:DropDownList ID="InstructorsDropDownList" runat="server" 
                        DataSourceID="InstructorsObjectDataSource"
                        DataTextField="FullName" DataValueField="PersonID" OnInit="DepartmentsDropDownList_Init">
                    </asp:DropDownList>
                </InsertItemTemplate>
            </asp:TemplateField>
            <asp:CommandField ShowInsertButton="True" />
        </Fields>
    </asp:DetailsView>
   <asp:ValidationSummary ID="DepartmentsValidationSummary" runat="server" 
        ShowSummary="true" DisplayMode="BulletList"  />

Tento kód vytvoří dva ObjectDataSource ovládací prvky, jeden pro vkládání nových Department entit a druhý pro načtení názvů instruktorů pro DropDownList ovládací prvek, který se používá pro výběr správců oddělení. Kód vytvoří DetailsView ovládací prvek pro zadávání nových oddělení a určuje obslužnou rutinu pro událost ovládacího prvku ItemInserting , abyste mohli nastavit hodnotu cizího Administrator klíče. Na konci je ovládací prvek ValidationSummary pro zobrazení chybových zpráv.

Otevřete DepartmentsAdd.aspx.cs a přidejte následující using příkaz:

using ContosoUniversity.DAL;

Přidejte následující proměnnou třídy a metody:

private DropDownList administratorsDropDownList;

protected void Page_Init(object sender, EventArgs e)
{
    DepartmentsDetailsView.EnableDynamicData(typeof(Department));
}

protected void DepartmentsDropDownList_Init(object sender, EventArgs e)
{
    administratorsDropDownList = sender as DropDownList;
}

protected void DepartmentsDetailsView_ItemInserting(object sender, DetailsViewInsertEventArgs e)
{
    e.Values["Administrator"] = administratorsDropDownList.SelectedValue;
}

Metoda Page_Init umožňuje funkci dynamických dat. Obslužná rutina události DropDownList ovládacího prvku Init uloží odkaz na ovládací prvek a obslužná rutina Inserting události DetailsView ovládacího prvku použije tento odkaz k získání PersonID hodnoty vybraného instruktora a aktualizaci Administrator vlastnosti cizího Department klíče entity.

Spusťte stránku, přidejte informace pro nové oddělení a klikněte na odkaz Vložit .

Obrázek04

Zadejte hodnoty pro jiné nové oddělení. Do pole Rozpočet zadejte číslo větší než 1 000 000,00 a tabulátorem přejděte na další pole. V poli se zobrazí hvězdička, a pokud na ni podržíte ukazatel myši, zobrazí se chybová zpráva, kterou jste zadali v metadatech pro toto pole.

Obrázek03

Klikněte na Vložit a zobrazí se chybová zpráva zobrazená ovládacím ValidationSummary prvku v dolní části stránky.

Obrázek 12

Pak zavřete prohlížeč a otevřete stránku Departments.aspx . Přidejte možnost odstranění na stránku Departments.aspx přidáním atributu DeleteMethodObjectDataSource do ovládacího prvku a DataKeyNames atributu GridView do ovládacího prvku. Počáteční značky pro tyto ovládací prvky se teď budou podobat následujícímu příkladu:

<asp:ObjectDataSource ID="DepartmentsObjectDataSource" runat="server" 
        TypeName="ContosoUniversity.DAL.SchoolRepository" 
        DataObjectTypeName="ContosoUniversity.DAL.Department"
        SelectMethod="GetDepartments" 
        DeleteMethod="DeleteDepartment" >

    <asp:GridView ID="DepartmentsGridView" runat="server" AutoGenerateColumns="False"
        DataSourceID="DepartmentsObjectDataSource" DataKeyNames="DepartmentID" >

Spusťte stránku.

Snímek obrazovky se stránkou Oddělení po spuštění

Odstraňte oddělení, které jste přidali při spuštění stránky DepartmentsAdd.aspx .

Přidání funkce aktualizace

Otevřete Soubor SchoolRepository.cs a přidejte následující Update metodu:

public void UpdateDepartment(Department department, Department origDepartment)
{
    try
    {
        context.Departments.Attach(origDepartment);
        context.ApplyCurrentValues("Departments", department);
        context.SaveChanges();
    }
    catch (Exception ex)
    {
        //Include catch blocks for specific exceptions first,
        //and handle or log the error as appropriate in each.
        //Include a generic catch block like this one last.
        throw ex;
    }
}

Když kliknete na Aktualizovat na stránce Departments.aspx , ObjectDataSource ovládací prvek vytvoří dvě Department entity, které se předávají UpdateDepartment metodě. Jedna obsahuje původní hodnoty, které byly uloženy ve stavu zobrazení, a druhá obsahuje nové hodnoty, které byly zadány v ovládacím GridView prvku. Kód v UpdateDepartment metodě předá entitu Department , která má původní hodnoty, metodě Attach , aby bylo možné vytvořit sledování mezi entitou a tím, co je v databázi. Pak kód předá entitu Department , která má nové hodnoty, metodě ApplyCurrentValues . Kontext objektu porovnává staré a nové hodnoty. Pokud se nová hodnota liší od staré hodnoty, kontext objektu změní hodnotu vlastnosti. Metoda SaveChanges pak aktualizuje pouze změněné sloupce v databázi. (Pokud by však funkce aktualizace pro tuto entitu byla namapována na uloženou proceduru, celý řádek by se aktualizoval bez ohledu na to, které sloupce byly změněny.)

Otevřete soubor Departments.aspx a přidejte do DepartmentsObjectDataSource ovládacího prvku následující atributy:

  • UpdateMethod="UpdateDepartment"
  • ConflictDetection="CompareAllValues"
    To způsobí, že staré hodnoty budou uloženy ve stavu zobrazení, aby je bylo možné porovnat s novými hodnotami v Update metodě.
  • OldValuesParameterFormatString="orig{0}"
    To informuje ovládací prvek, že název původního parametru hodnot je origDepartment .

Kód pro počáteční značku ovládacího prvku ObjectDataSource se teď podobá následujícímu příkladu:

<asp:ObjectDataSource ID="DepartmentsObjectDataSource" runat="server" 
        TypeName="ContosoUniversity.DAL.SchoolRepository" 
        DataObjectTypeName="ContosoUniversity.DAL.Department" 
        SelectMethod="GetDepartments" DeleteMethod="DeleteDepartment" 
        UpdateMethod="UpdateDepartment"
        ConflictDetection="CompareAllValues" 
        OldValuesParameterFormatString="orig{0}" >

OnRowUpdating="DepartmentsGridView_RowUpdating" Přidejte do GridView ovládacího prvku atribut. Použijete ji k nastavení Administrator hodnoty vlastnosti na základě řádku, který uživatel vybere v rozevíracím seznamu. Počáteční GridView značka se teď podobá následujícímu příkladu:

<asp:GridView ID="DepartmentsGridView" runat="server" AutoGenerateColumns="False"
        DataSourceID="DepartmentsObjectDataSource" DataKeyNames="DepartmentID"
        OnRowUpdating="DepartmentsGridView_RowUpdating">

Přidejte ovládací prvek EditItemTemplate pro sloupec do GridView ovládacího prvku hned za ItemTemplate ovládací prvek Administrator pro daný sloupec:

<EditItemTemplate>
                    <asp:ObjectDataSource ID="InstructorsObjectDataSource" runat="server" DataObjectTypeName="ContosoUniversity.DAL.InstructorName"
                        SelectMethod="GetInstructorNames" TypeName="ContosoUniversity.DAL.SchoolRepository">
                    </asp:ObjectDataSource>
                    <asp:DropDownList ID="InstructorsDropDownList" runat="server" DataSourceID="InstructorsObjectDataSource"
                        SelectedValue='<%# Eval("Administrator")  %>'
                        DataTextField="FullName" DataValueField="PersonID" OnInit="DepartmentsDropDownList_Init" >
                    </asp:DropDownList>
                </EditItemTemplate>

Tento EditItemTemplate ovládací prvek je podobný ovládacímu InsertItemTemplate prvku na stránce DepartmentsAdd.aspx . Rozdíl je v tom, že počáteční hodnota ovládacího prvku je nastavena pomocí atributu SelectedValue .

Před ovládací prvek GridView přidejte ValidationSummary ovládací prvek, jak jste to udělali na stránce DepartmentsAdd.aspx .

<asp:ValidationSummary ID="DepartmentsValidationSummary" runat="server" 
        ShowSummary="true" DisplayMode="BulletList"  />

Otevřete Departments.aspx.cs a ihned po deklaraci částečné třídy přidejte následující kód pro vytvoření privátního pole odkazovaného na DropDownList ovládací prvek:

private DropDownList administratorsDropDownList;

Pak přidejte obslužné rutiny pro DropDownList událost ovládacího prvku Init a GridView událost ovládacího prvku RowUpdating :

protected void DepartmentsDropDownList_Init(object sender, EventArgs e)
{
    administratorsDropDownList = sender as DropDownList;
}

protected void DepartmentsGridView_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
    e.NewValues["Administrator"] = administratorsDropDownList.SelectedValue;
}

Obslužná rutina události Init uloží odkaz na DropDownList ovládací prvek v poli třídy. Obslužná rutina události RowUpdating používá odkaz k získání hodnoty, kterou uživatel zadal, a použije ji pro Administrator vlastnost Department entity.

Pomocí stránky DepartmentsAdd.aspx přidejte nové oddělení, spusťte stránku Departments.aspx a klikněte na upravit na řádku, který jste přidali.

Poznámka

Nebudete moci upravit řádky, které jste nepřidali (to znamená, že již byly v databázi), z důvodu neplatných dat v databázi; správci řádků vytvořených s databází jsou studenti. Pokud se pokusíte některý z nich upravit, zobrazí se chybová stránka, která hlásí chybu, například 'InstructorsDropDownList' has a SelectedValue which is invalid because it does not exist in the list of items.

Obrázek 10

Pokud zadáte neplatnou částku rozpočtu a potom kliknete na Aktualizovat, zobrazí se stejná hvězdička a chybová zpráva, jakou jste viděli na stránce Departments.aspx .

Změňte hodnotu pole nebo vyberte jiného správce a klikněte na Aktualizovat. Zobrazí se změna.

Snímek obrazovky se stránkou Oddělení

Tím se dokončí úvod k používání ObjectDataSource ovládacího prvku pro základní operace CRUD (vytvoření, čtení, aktualizace, odstranění) s rozhraním Entity Framework. Vytvořili jste jednoduchou n-vrstvou aplikaci, ale vrstva obchodní logiky je stále úzce spojená s vrstvou přístupu k datům, což komplikuje automatizované testování částí. V následujícím kurzu se dozvíte, jak implementovat vzor úložiště pro usnadnění testování částí.