Sdílet prostřednictvím


Začínáme s Entity Framework 4.0 Database First a ASP.NET 4 Web Forms – část 5

Tom Dykstra

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. Informace o sérii kurzů najdete v prvním kurzu v této řadě.

V předchozím kurzu jste začali používat EntityDataSource ovládací prvek k práci se souvisejícími daty. Ve vlastnostech navigace jste zobrazili několik úrovní hierarchie a upravili jste data. V tomto kurzu budete pokračovat v práci se souvisejícími daty přidáním a odstraněním relací a přidáním nové entity, která má relaci k existující entitě.

Vytvoříte stránku, která přidá kurzy přiřazené k oddělením. Oddělení už existují, a když vytvoříte nový kurz, současně vytvoříte vztah mezi ním a existujícím oddělením.

Snímek obrazovky s oknem Internet Exploreru, které zobrazuje zobrazení Přidat kurzy s textovými poli ID, Název a Kredity a rozevíracím seznamem Oddělení

Vytvoříte také stránku, která funguje se vztahem M:N tím, že přiřadíte instruktora ke kurzu (přidáte relaci mezi dvěma entitami, které vyberete) nebo odeberete instruktora z kurzu (odeberete relaci mezi dvěma entitami, které vyberete). Přidání relace mezi instruktorem a kurzem v databázi způsobí přidání nového řádku do CourseInstructor asociační tabulky. Odebrání relace zahrnuje odstranění řádku z CourseInstructor asociační tabulky. Provedete to však v Entity Frameworku nastavením navigačních vlastností bez explicitního odkazu na CourseInstructor tabulku.

Snímek obrazovky s oknem Internet Exploreru, které zobrazuje zobrazení Přiřadit instruktory ke kurzům nebo Odebrat z kurzů

Přidání entity s relací k existující entitě

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

<h2>Add Courses</h2>
    <asp:EntityDataSource ID="CoursesEntityDataSource" runat="server" 
        ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
        EntitySetName="Courses" 
        EnableInsert="True" EnableDelete="True" >
    </asp:EntityDataSource>
    <asp:DetailsView ID="CoursesDetailsView" runat="server" AutoGenerateRows="False"
        DataSourceID="CoursesEntityDataSource" DataKeyNames="CourseID"
        DefaultMode="Insert" oniteminserting="CoursesDetailsView_ItemInserting">
        <Fields>
            <asp:BoundField DataField="CourseID" HeaderText="ID" />
            <asp:BoundField DataField="Title" HeaderText="Title" />
            <asp:BoundField DataField="Credits" HeaderText="Credits" />
            <asp:TemplateField HeaderText="Department">
                <InsertItemTemplate>
                    <asp:EntityDataSource ID="DepartmentsEntityDataSource" runat="server" ConnectionString="name=SchoolEntities"
                        DefaultContainerName="SchoolEntities" EnableDelete="True" EnableFlattening="False"
                        EntitySetName="Departments" EntityTypeFilter="Department">
                    </asp:EntityDataSource>
                    <asp:DropDownList ID="DepartmentsDropDownList" runat="server" DataSourceID="DepartmentsEntityDataSource"
                        DataTextField="Name" DataValueField="DepartmentID"
                        oninit="DepartmentsDropDownList_Init">
                    </asp:DropDownList>
                </InsertItemTemplate>
            </asp:TemplateField>
            <asp:CommandField ShowInsertButton="True" />
        </Fields>
    </asp:DetailsView>

Tato značka vytvoří ovládací prvek EntityDataSource , který vybere kurzy, který umožňuje vkládání a který určuje obslužnou rutinu Inserting události. Obslužnou rutinu použijete k aktualizaci Department navigační vlastnosti při vytvoření nové Course entity.

Značka také vytvoří ovládací prvek, který DetailsView se použije pro přidávání nových Course entit. Značky používají pro Course vlastnosti entity svázaná pole. Musíte zadat hodnotu, CourseID protože se nejedná o pole ID generované systémem. Místo toho se jedná o číslo kurzu, které se musí při vytvoření kurzu zadat ručně.

Pro vlastnost navigace použijete pole Department šablony, protože vlastnosti navigace nelze použít s ovládacími BoundField prvky. Pole šablony obsahuje rozevírací seznam pro výběr oddělení. Rozevírací seznam je vázán na Departments sadu entit pomocí namísto EvalBind, protože nelze přímo svázat navigační vlastnosti, abyste je mohli aktualizovat. Zadáte obslužnou rutinu DropDownList pro událost ovládacího prvku Init , abyste mohli uložit odkaz na ovládací prvek pro použití kódem, který aktualizuje DepartmentID cizí klíč.

V souboru CoursesAdd.aspx.cs těsně za deklaraci částečné třídy přidejte pole třídy, které bude obsahovat odkaz na DepartmentsDropDownList ovládací prvek:

private DropDownList departmentDropDownList;

Přidejte obslužnou rutinu DepartmentsDropDownList pro událost ovládacího prvku Init , abyste mohli uložit odkaz na ovládací prvek. To vám umožní získat hodnotu, kterou uživatel zadal, a použít ji k aktualizaci DepartmentID hodnoty Course entity.

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

Přidejte obslužnou rutinu DetailsView pro událost ovládacího prvku Inserting :

protected void CoursesDetailsView_ItemInserting(object sender, DetailsViewInsertEventArgs e)
{
    var departmentID = Convert.ToInt32(departmentDropDownList.SelectedValue);
    e.Values["DepartmentID"] = departmentID;
}

Když uživatel klikne na Insert, Inserting událost se vyvolá před vložením nového záznamu. Kód v obslužné rutině získá DepartmentID z DropDownList ovládacího prvku a použije ho k nastavení hodnoty, která se použije pro DepartmentID vlastnost Course entity.

Entity Framework se postará o přidání tohoto kurzu do Courses vlastnosti navigace přidružené Department entity. Také přidá oddělení do Department vlastnosti Course navigace entity.

Spusťte stránku.

Snímek obrazovky s oknem Internet Exploreru, které zobrazuje zobrazení Přidat kurzy s textovými poli ID, Název a Kredity a rozevíracím seznamem Oddělení

Zadejte ID, titul, počet kreditů, vyberte oddělení a klikněte na Vložit.

Spusťte stránku Courses.aspx a vyberte stejné oddělení, abyste viděli nový kurz.

Obrázek03

Práce s relacemi M:N

Relace mezi Courses sadou entit a People sadou entit je relace M:N. Entita Course má navigační vlastnost s názvem People , která může obsahovat nula, jednu nebo více souvisejících Person entit (představující instruktory přiřazené k výuce daného kurzu). Entita Person má navigační vlastnost s názvem Courses , která může obsahovat nula, jednu nebo více souvisejících Course entit (což představuje kurzy, které má instruktor přiřazený k výuce). Jeden instruktor může vyučovat více kurzů a jeden kurz může vyučovat více instruktorů. V této části návodu přidáte a odeberete relace mezi Person entitami a Course aktualizací navigačních vlastností souvisejících entit.

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

<h2>Assign Instructors to Courses or Remove from Courses</h2>
    <br />
    <asp:EntityDataSource ID="InstructorsEntityDataSource" runat="server" 
        ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False" 
        EntitySetName="People"
        Where="it.HireDate is not null" Select="it.LastName + ', ' + it.FirstMidName AS Name, it.PersonID">
    </asp:EntityDataSource>
    Select an Instructor:
    <asp:DropDownList ID="InstructorsDropDownList" runat="server" DataSourceID="InstructorsEntityDataSource"
        AutoPostBack="true" DataTextField="Name" DataValueField="PersonID"
        OnSelectedIndexChanged="InstructorsDropDownList_SelectedIndexChanged" 
        OnDataBound="InstructorsDropDownList_DataBound">
    </asp:DropDownList>
    <h3>
        Assign a Course</h3>
    <br />
    Select a Course:
    <asp:DropDownList ID="UnassignedCoursesDropDownList" runat="server"
        DataTextField="Title" DataValueField="CourseID">
    </asp:DropDownList>
    <br />
    <asp:Button ID="AssignCourseButton" runat="server" Text="Assign" OnClick="AssignCourseButton_Click" />
    <br />
    <asp:Label ID="CourseAssignedLabel" runat="server" Visible="false" Text="Assignment successful"></asp:Label>
    <br />
    <h3>
        Remove a Course</h3>
    <br />
    Select a Course:
    <asp:DropDownList ID="AssignedCoursesDropDownList" runat="server"
        DataTextField="title" DataValueField="courseiD">
    </asp:DropDownList>
    <br />
    <asp:Button ID="RemoveCourseButton" runat="server" Text="Remove" OnClick="RemoveCourseButton_Click" />
    <br />
    <asp:Label ID="CourseRemovedLabel" runat="server" Visible="false" Text="Removal successful"></asp:Label>

Tato značka vytvoří ovládací prvekEntityDataSource, který načte název a PersonPersonID entity pro instruktory. Ovládací DropDrownList prvek je vázán na EntityDataSource ovládací prvek. Ovládací DropDownList prvek určuje obslužnou rutinu DataBound události. Tuto obslužnou rutinu použijete k vytvoření vazby dvou rozevíracích seznamů, které zobrazují kurzy.

Přirážka také vytvoří následující skupinu ovládacích prvků, které se použijí pro přiřazení kurzu vybranému instruktoru:

  • Ovládací DropDownList prvek pro výběr kurzu, který chcete přiřadit. Tento ovládací prvek bude naplněn kurzy, které aktuálně nejsou přiřazeny vybranému instruktorovi.
  • Ovládací Button prvek pro zahájení přiřazení.
  • Ovládací Label prvek, který zobrazí chybovou zprávu, pokud přiřazení selže.

Nakonec přirážka vytvoří také skupinu ovládacích prvků, které se použijí k odebrání kurzu vybranému instruktoru.

V části InstructorsCourses.aspx.cs přidejte příkaz using:

using ContosoUniversity.DAL;

Přidejte metodu pro naplnění dvou rozevíracích seznamů, které zobrazují kurzy:

private void PopulateDropDownLists()
{
    using (var context = new SchoolEntities())
    {
        var allCourses = (from c in context.Courses
                          select c).ToList();

        var instructorID = Convert.ToInt32(InstructorsDropDownList.SelectedValue);
        var instructor = (from p in context.People.Include("Courses")
                          where p.PersonID == instructorID
                          select p).First();

        var assignedCourses = instructor.Courses.ToList();
        var unassignedCourses = allCourses.Except(assignedCourses.AsEnumerable()).ToList();

        UnassignedCoursesDropDownList.DataSource = unassignedCourses;
        UnassignedCoursesDropDownList.DataBind();
        UnassignedCoursesDropDownList.Visible = true;

        AssignedCoursesDropDownList.DataSource = assignedCourses;
        AssignedCoursesDropDownList.DataBind();
        AssignedCoursesDropDownList.Visible = true;
    }
}

Tento kód získá všechny kurzy ze Courses sady entit a kurzy získá z Courses navigační vlastnosti Person entity pro vybraného instruktora. Pak určí, které kurzy budou přiřazeny danému instruktorovi, a odpovídajícím způsobem naplní rozevírací seznamy.

Přidejte obslužnou rutinu Assign pro událost tlačítka Click :

protected void AssignCourseButton_Click(object sender, EventArgs e)
{
    using (var context = new SchoolEntities())
    {
        var instructorID = Convert.ToInt32(InstructorsDropDownList.SelectedValue);
        var instructor = (from p in context.People
                          where p.PersonID == instructorID
                          select p).First();
        var courseID = Convert.ToInt32(UnassignedCoursesDropDownList.SelectedValue);
        var course = (from c in context.Courses
                      where c.CourseID == courseID
                      select c).First();
        instructor.Courses.Add(course);
        try
        {
            context.SaveChanges();
            PopulateDropDownLists();
            CourseAssignedLabel.Text = "Assignment successful.";
        }
        catch (Exception)
        {
            CourseAssignedLabel.Text = "Assignment unsuccessful.";
            //Add code to log the error.
        }
        CourseAssignedLabel.Visible = true;
    }
}

Tento kód získá entitu Person pro vybraného instruktora, získá entitu Course pro vybraný kurz a přidá vybraný kurz do Courses vlastnosti navigace entity instruktora Person . Pak uloží změny do databáze a znovu naplní rozevírací seznamy, aby se výsledky okamžitě zobrazily.

Přidejte obslužnou rutinu Remove pro událost tlačítka Click :

protected void RemoveCourseButton_Click(object sender, EventArgs e)
{
    using (var context = new SchoolEntities())
    {
        var instructorID = Convert.ToInt32(InstructorsDropDownList.SelectedValue);
        var instructor = (from p in context.People
                          where p.PersonID == instructorID
                          select p).First();
        var courseID = Convert.ToInt32(AssignedCoursesDropDownList.SelectedValue);
        var courses = instructor.Courses;
        var courseToRemove = new Course();
        foreach (Course c in courses)
        {
            if (c.CourseID == courseID)
            {
                courseToRemove = c;
                break;
            }
        }
        try
        {
            courses.Remove(courseToRemove);
            context.SaveChanges();
            PopulateDropDownLists();
            CourseRemovedLabel.Text = "Removal successful.";
        }
        catch (Exception)
        {
            CourseRemovedLabel.Text = "Removal unsuccessful.";
            //Add code to log the error.
        }
        CourseRemovedLabel.Visible = true;
    }
}

Tento kód získá entitu Person pro vybraného instruktora, získá entitu Course pro vybraný kurz a odebere vybraný kurz z Person vlastnosti navigace entity Courses . Pak uloží změny do databáze a znovu naplní rozevírací seznamy, aby se výsledky okamžitě zobrazily.

Přidejte do Page_Load metody kód, který zajistí, že chybové zprávy nejsou viditelné, pokud není k dispozici žádná chyba, která by se nahlásila, a přidejte obslužné rutiny pro DataBound události a SelectedIndexChanged rozevíracího seznamu instruktorů, které naplní rozevírací seznamy kurzů:

protected void Page_Load(object sender, EventArgs e)
{
    CourseAssignedLabel.Visible = false;
    CourseRemovedLabel.Visible = false;
}

protected void InstructorsDropDownList_DataBound(object sender, EventArgs e)
{
    PopulateDropDownLists();
}

protected void InstructorsDropDownList_SelectedIndexChanged(object sender, EventArgs e)
{
    PopulateDropDownLists();
}

Spusťte stránku.

Snímek obrazovky s oknem Internet Exploreru, které zobrazuje zobrazení Přiřadit instruktory ke kurzům nebo Odebrat z kurzů s odpovídajícími rozevíracími seznamy

Vyberte instruktora. V rozevíracím seznamu Přiřadit kurz se zobrazí kurzy, které instruktor nevyučuje, a v rozevíracím seznamu Odebrat kurz se zobrazí kurzy, ke kterým už je instruktor přiřazený. V části Přiřadit kurz vyberte kurz a klikněte na Přiřadit. Kurz se přesune do rozevíracího seznamu Odebrat kurz . Vyberte kurz v části Odebrat kurz a klikněte na Odebrat. Kurz se přesune do rozevíracího seznamu Přiřadit kurz .

Teď jste viděli několik dalších způsobů, jak pracovat se souvisejícími daty. V následujícím kurzu se dozvíte, jak pomocí dědičnosti v datovém modelu zlepšit udržovatelnost vaší aplikace.