Udostępnij za pośrednictwem


Wprowadzenie z programem Entity Framework 4.0 Database First i ASP.NET 4 Web Forms — część 5

Autor : Tom Dykstra

Przykładowa aplikacja internetowa Contoso University pokazuje, jak tworzyć aplikacje ASP.NET Web Forms przy użyciu platform Entity Framework 4.0 i Visual Studio 2010. Aby uzyskać informacje na temat serii samouczków, zobacz pierwszy samouczek z serii

W poprzednim samouczku rozpoczęto korzystanie z kontrolki EntityDataSource do pracy z powiązanymi danymi. W właściwościach nawigacji wyświetlane są wiele poziomów hierarchii i edytowane dane. W tym samouczku będziesz nadal pracować z powiązanymi danymi, dodając i usuwając relacje oraz dodając nową jednostkę, która ma relację z istniejącą jednostką.

Utworzysz stronę, która dodaje kursy przypisane do działów. Działy już istnieją i podczas tworzenia nowego kursu ustanowisz relację między nim i istniejącym działem.

Zrzut ekranu przedstawiający okno programu Internet Explorer z polami tekstowymi Dodawanie kursów z polami tekstowymi Identyfikator, Tytuł i Środki oraz listą rozwijaną Dział.

Utworzysz również stronę, która współpracuje z relacją wiele-do-wielu, przypisując instruktora do kursu (dodając relację między dwoma wybranymi jednostkami) lub usuwając instruktora z kursu (usuwając relację między dwoma wybranymi jednostkami). W bazie danych dodanie relacji między instruktorem a kursem powoduje dodanie nowego wiersza do CourseInstructor tabeli skojarzeń. Usunięcie relacji obejmuje usunięcie wiersza z CourseInstructor tabeli skojarzeń. Można to jednak zrobić w programie Entity Framework, ustawiając właściwości nawigacji bez jawnego CourseInstructor odwoływania się do tabeli.

Zrzut ekranu przedstawiający okno programu Internet Explorer z widokiem Przypisywanie instruktorów do kursów lub Usuwanie z kursów.

Dodawanie jednostki z relacją do istniejącej jednostki

Utwórz nową stronę internetową o nazwie CoursesAdd.aspx korzystającą ze strony wzorcowej Site.Master i dodaj następujący znacznik do kontrolki Content o nazwie Content2:

<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>

Ten znacznik tworzy kontrolkę EntityDataSource , która wybiera kursy, która umożliwia wstawianie i określa procedurę obsługi dla zdarzenia Inserting . Użyjesz procedury obsługi, aby zaktualizować właściwość nawigacji po utworzeniu Department nowej Course jednostki.

Znacznik tworzy również kontrolkę służącą DetailsView do dodawania nowych Course jednostek. Znacznik używa pól powiązanych dla Course właściwości jednostki. Musisz wprowadzić CourseID wartość, ponieważ nie jest to pole identyfikatora generowanego przez system. Zamiast tego jest to numer kursu, który należy określić ręcznie podczas tworzenia kursu.

Dla właściwości nawigacji jest używane pole Department szablonu, ponieważ nie można używać właściwości nawigacji z kontrolkami BoundField . Pole szablonu zawiera listę rozwijaną do wybrania działu. Lista rozwijana jest powiązana z zestawem Departments jednostek za pomocą polecenia Eval , a nie Bind, ponieważ nie można bezpośrednio powiązać właściwości nawigacji w celu ich zaktualizowania. Należy określić procedurę obsługi dla DropDownList zdarzenia kontrolki Init , aby można było przechowywać odwołanie do kontrolki do użycia przez kod aktualizujący DepartmentID klucz obcy.

W pliku CoursesAdd.aspx.cs tuż po deklaracji częściowej klasy dodaj pole klasy do przechowywania odwołania do kontrolki DepartmentsDropDownList :

private DropDownList departmentDropDownList;

Dodaj procedurę obsługi dla DepartmentsDropDownList zdarzenia kontrolki Init , aby można było przechowywać odwołanie do kontrolki. Dzięki temu można uzyskać wartość wprowadzoną przez użytkownika i użyć jej do zaktualizowania DepartmentID wartości Course jednostki.

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

Dodaj procedurę obsługi dla DetailsView zdarzenia kontrolki Inserting :

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

Gdy użytkownik kliknie Insertprzycisk , Inserting zdarzenie zostanie zgłoszone przed wstawionym nowym rekordem. Kod w procedurze obsługi pobiera element DepartmentID z kontrolki DropDownList i używa go do ustawienia wartości, która będzie używana dla DepartmentID właściwości Course jednostki.

Program Entity Framework zajmie się dodaniem tego kursu do Courses właściwości nawigacji skojarzonej Department jednostki. Dodaje również dział do Department właściwości Course nawigacji jednostki.

Uruchom stronę.

Zrzut ekranu przedstawiający okno programu Internet Explorer z polami tekstowymi Dodawanie kursów z polami tekstowymi Identyfikator, Tytuł i Środki oraz listą rozwijaną Dział.

Wprowadź identyfikator, tytuł, liczbę środków i wybierz dział, a następnie kliknij pozycję Wstaw.

Uruchom stronę Courses.aspx i wybierz ten sam dział, aby zobaczyć nowy kurs.

Obraz03

Praca z relacjami wiele-do-wielu

Relacja między zestawem Courses jednostek a People zestawem jednostek jest relacją wiele do wielu. Jednostka Course ma właściwość nawigacji o nazwie People , która może zawierać zero, co najmniej jedną powiązaną Person jednostkę (reprezentując instruktorów przypisanych do nauczania tego kursu). Person Jednostka ma właściwość nawigacji o nazwie Courses , która może zawierać zero, co najmniej jedną powiązaną Course jednostkę (reprezentując kursy przypisane przez instruktora do nauczania). Jeden z instruktorów może uczyć się wielu kursów, a jeden kurs może być nauczany przez wielu instruktorów. W tej sekcji przewodnika dodasz i usuniesz relacje między jednostkami Person i Course , aktualizując właściwości nawigacji powiązanych jednostek.

Utwórz nową stronę internetową o nazwie InstructorsCourses.aspx korzystającą ze strony wzorcowej Site.Master i dodaj następujący znacznik do kontrolki Content o nazwie Content2:

<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>

Ten znacznik tworzy kontrolkę EntityDataSource , która pobiera nazwę i PersonIDPerson jednostki dla instruktorów. Kontrolka DropDrownList jest powiązana z kontrolką EntityDataSource . Kontrolka DropDownList określa procedurę obsługi zdarzenia DataBound . Użyjesz tej procedury obsługi do powiązania dwóch list rozwijanych, które wyświetlają kursy.

Znacznik tworzy również następującą grupę kontrolek, które mają być używane do przypisywania kursu do wybranego instruktora:

  • Kontrolka DropDownList wybierania kursu do przypisania. Ta kontrolka zostanie wypełniona kursami, które nie są obecnie przypisane do wybranego instruktora.
  • Kontrolka Button inicjowania przypisania.
  • Kontrolka Label wyświetla komunikat o błędzie, jeśli przypisanie nie powiedzie się.

Na koniec adiustacja tworzy również grupę kontrolek, które mają być używane do usuwania kursu z wybranego instruktora.

W pliku InstructorsCourses.aspx.cs dodaj instrukcję using:

using ContosoUniversity.DAL;

Dodaj metodę wypełniania dwóch list rozwijanych, które wyświetlają kursy:

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;
    }
}

Ten kod pobiera wszystkie kursy z Courses zestawu jednostek i pobiera kursy z Courses właściwości Person nawigacji jednostki dla wybranego instruktora. Następnie określa, które kursy są przypisane do tego instruktora i odpowiednio wypełnia listy rozwijane.

Dodaj procedurę obsługi dla Assign zdarzenia przycisku 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;
    }
}

Ten kod pobiera Person jednostkę dla wybranego instruktora, pobiera Course jednostkę dla wybranego kursu i dodaje wybrany kurs do Courses właściwości nawigacji jednostki instruktora Person . Następnie zapisuje zmiany w bazie danych i ponownie wypełnia listy rozwijane, aby wyniki były widoczne natychmiast.

Dodaj procedurę obsługi dla Remove zdarzenia przycisku 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;
    }
}

Ten kod pobiera Person jednostkę dla wybranego instruktora, pobiera Course jednostkę dla wybranego kursu i usuwa wybrany kurs z Person właściwości nawigacji jednostki Courses . Następnie zapisuje zmiany w bazie danych i ponownie wypełnia listy rozwijane, aby wyniki były widoczne natychmiast.

Dodaj kod do Page_Load metody, która zapewnia, że komunikaty o błędach nie są widoczne, gdy nie ma żadnego błędu do raportowania, i dodaj programy obsługi dla DataBound listy rozwijanej i SelectedIndexChanged zdarzeń instruktorów, aby wypełnić listy rozwijane kursów:

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();
}

Uruchom stronę.

Zrzut ekranu przedstawiający okno programu Internet Explorer z listami rozwijanymi Przypisz instruktorów do kursów lub Usuń z kursów.

Wybierz instruktora. Lista rozwijana Przypisz kurs zawiera kursy, których instruktor nie uczy, a lista rozwijana Usuń kurs zawiera kursy, do których jest już przypisany instruktor. W sekcji Przypisywanie kursu wybierz kurs, a następnie kliknij pozycję Przypisz. Kurs przechodzi do listy rozwijanej Usuń kurs . Wybierz kurs w sekcji Usuń kurs , a następnie kliknij przycisk Usuń. Kurs zostanie przeniesiony do listy rozwijanej Przypisz kurs .

Znasz już kilka sposobów pracy z powiązanymi danymi. W poniższym samouczku dowiesz się, jak używać dziedziczenia w modelu danych, aby zwiększyć łatwość konserwacji aplikacji.