共用方式為


消費者入門 Entity Framework 4.0 Database First 和 ASP.NET 4 Web Form - 第 2 部分

By Tom Dykstra

Contoso University 範例 Web 應用程式示範如何使用 Entity Framework 4.0 和 Visual Studio 2010 建立 ASP.NET Web Forms應用程式。 如需教學課程系列的相關資訊,請參閱 系列中的第一個教學課程

EntityDataSource 控制項

在上一個教學課程中,您已建立網站、資料庫和資料模型。 在本教學課程中,您會使用 EntityDataSource ASP.NET 提供的控制項,以便輕鬆地使用 Entity Framework 資料模型。 您將建立 GridView 控制項來顯示和編輯學生資料、 DetailsView 新增新學生的控制項,以及 DropDownList 選取部門 (的控制項,稍後您將用來顯示相關聯的課程) 。

Internet Explorer 視窗的螢幕擷取畫面,其中顯示 [學生清單] 檢視,其中包含學生名稱、註冊日期和課程的清單。

Internet Explorer 視窗的螢幕擷取畫面,其中顯示 [新增學生] 檢視,其中已填入文字欄位的 John Smith 名稱和註冊日期。

Internet Explorer 視窗的螢幕擷取畫面,其中顯示 [依部門] 檢視的 [課程] 檢視,其中包含部門下拉式功能表。

請注意,在此應用程式中,您不會將輸入驗證新增至更新資料庫的頁面,而某些錯誤處理不會像生產應用程式中所需的一樣強固。 這會讓教學課程著重于 Entity Framework,並讓它變得太長。 如需如何將這些功能新增至應用程式的詳細資訊,請參閱在頁面和應用程式中驗證 ASP.NET ASP.NET Web Pages中的使用者輸入和錯誤處理

新增和設定 EntityDataSource 控制項

首先,您將設定 EntityDataSource 控制項以從 People 實體集讀取 Person 實體。

請確定您已開啟 Visual Studio,並且正在使用您在第 1 部分中建立的專案。 如果您自從建立資料模型或上次變更之後尚未建置專案,請立即建置專案。 在建置專案之前,資料模型的變更不會提供給設計工具使用。

使用主版頁面範本使用 Web 表單 建立新的網頁,並將它命名為 Students.aspx

Image23

Site.Master 指定為主版頁面。 您為這些教學課程建立的所有頁面都會使用此主版頁面。

Image24

[來源 ] 檢視中,將標題新增 h2Content 名為 的 Content2 控制項,如下列範例所示:

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
   <h2>Student List</h2>
</asp:Content>

[工具箱] 的 [資料] 索引標籤中,將控制項拖曳 EntityDataSource 至頁面,將它放在標題下方,然後將識別碼變更為 StudentsEntityDataSource

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Student List</h2>
    <asp:EntityDataSource ID="StudentsEntityDataSource" runat="server">
    </asp:EntityDataSource>
</asp:Content>

切換至 [設計] 檢視,按一下資料來源控制項的智慧標籤,然後按一下 [ 設定 資料來源] 以啟動 [ 設定資料來源 精靈]。

Image01

在 [ 設定 ObjectCoNtext 精 靈] 步驟中,選取 [SchoolEntities ] 作為 [具名連線] 的值,然後選取 [SchoolEntities ] 作為 DefaultContainerName 值。 然後按一下 [下一步] 。

Image02

注意:如果您此時收到下列對話方塊,您必須先建置專案,再繼續進行。

Image25

在 [設定資料選取] 步驟中,選取[人員] 作為EntitySetName的值。 在 [ 選取] 底下,確定已選取 [ 選取 A ] 核取方塊。 然後選取啟用更新和刪除的選項。 完成時,按一下 [ 完成]。

Image03

設定資料庫規則以允許刪除

您將建立一個頁面,讓使用者從 Person 資料表中刪除學生,此資料表與其他資料表有三個關聯性, (CourseStudentGradeOfficeAssignment) 。 根據預設,如果其中一個資料表中有相關資料列,資料庫將無法刪除 中的資料 Person 列。 您可以先手動刪除相關資料列,也可以設定資料庫,以在刪除資料 Person 列時自動刪除它們。 針對本教學課程中的學生記錄,您將設定資料庫來自動刪除相關資料。 因為學生只能在資料表中 StudentGrade 擁有相關資料列,所以您只需要設定三個關聯性的其中一個。

如果您使用從本教學課程隨附的專案下載的 School.mdf 檔案,您可以略過本節,因為這些組態變更已經完成。 如果您藉由執行腳本來建立資料庫,請執行下列程式來設定資料庫。

[伺服器總管] 中,開啟您在第 1 部分中建立的資料庫關係圖。 以滑鼠右鍵按一下 和 StudentGrade 之間的關聯性, (資料表之間的 Person 行) ,然後選取 [屬性]。

Image04

在 [ 屬性 ] 視窗中,展開 INSERT 和 UPDATE 規格 ,並將 DeleteRule 屬性設定為 Cascade

Image05

儲存並關閉圖表。 如果系統詢問您是否要更新資料庫,請按一下 [ ]。

若要確定模型會讓記憶體中的實體與資料庫執行的動作保持同步,您必須在資料模型中設定對應的規則。 開啟SchoolModel.edmx,以滑鼠右鍵按一下 和 StudentGrade 之間的 Person 關聯線,然後選取 [屬性]。

Image21

在 [ 屬性] 視窗中,將 End1 OnDelete 設定為 Cascade

Image22

儲存並關閉 SchoolModel.edmx 檔案,然後重建專案。

一般而言,當資料庫變更時,您有數個如何同步處理模型的選項:

  • 對於某些類型的變更 (,例如新增或重新整理資料表、檢視或預存程式) ,請在設計工具中按一下滑鼠右鍵,然後從資料庫選取 [ 更新模型 ],讓設計工具自動進行變更。
  • 重新產生資料模型。
  • 像這樣進行手動更新。

在此情況下,您可以重新產生模型或重新整理受關聯性變更影響的資料表,但您必須再次變更功能變數名稱, (FirstName 變更為 FirstMidName) 。

使用 GridView 控制項讀取和更新實體

在本節中,您將使用 GridView 控制項來顯示、更新或刪除學生。

開啟或切換至 Students.aspx ,並切換至 [設計] 檢視。 從[工具箱] 的 [資料] 索引標籤中,將控制項拖曳 GridView 到控制項右邊 EntityDataSource ,將它 StudentsGridView 命名為 ,按一下智慧標籤,然後選取StudentsEntityDataSource作為資料來源。

Image06

如果系統提示您確認) ,請按一下 [ 重新整理架構 ] (按一下 [ ],然後按一下 [ 啟用分頁]、[ 啟用排序]、[ 啟用編輯] 和 [ 啟用刪除]。

按一下 [編輯資料行]。

Image10

在 [ 選取的欄位] 方塊 中,刪除 PersonIDLastNameHireDate。 您通常不會向使用者顯示記錄索引鍵、雇用日期與學生無關,而且您會將這兩個部分的名稱放在一個欄位中,因此您只需要其中一個名稱欄位。)

Image11

選取 [FirstMidName] 欄位,然後按一下 [ 將此欄位轉換成 TemplateField]。

針對 EnrollmentDate執行相同的動作。

Image13

按一下 [確定 ],然後切換至 [來源 ] 檢視。 其餘的變更將更容易直接在標記中執行。 控制項 GridView 標記現在看起來像下列範例。

<asp:GridView ID="StudentsGridView" runat="server" AllowPaging="True" 
        AllowSorting="True" AutoGenerateColumns="False" DataKeyNames="PersonID" 
        DataSourceID="StudentsEntityDataSource">
        <Columns>
            <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
            <asp:TemplateField HeaderText="FirstMidName" SortExpression="FirstMidName">
                <EditItemTemplate>
                    <asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("FirstMidName") %>'></asp:TextBox>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:Label ID="Label1" runat="server" Text='<%# Bind("FirstMidName") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="EnrollmentDate" SortExpression="EnrollmentDate">
                <EditItemTemplate>
                    <asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("EnrollmentDate") %>'></asp:TextBox>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:Label ID="Label2" runat="server" Text='<%# Bind("EnrollmentDate") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

命令欄位後面的第一個資料行是目前顯示名字的範本欄位。 變更此範本欄位的標記,如下所示:

<asp:TemplateField HeaderText="Name" SortExpression="LastName">
                <EditItemTemplate>
                    <asp:TextBox ID="LastNameTextBox" runat="server" Text='<%# Bind("LastName") %>'></asp:TextBox>
                    <asp:TextBox ID="FirstNameTextBox" runat="server" Text='<%# Bind("FirstMidName") %>'></asp:TextBox>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:Label ID="LastNameLabel" runat="server" Text='<%# Eval("LastName") %>'></asp:Label>,
                    <asp:Label ID="FirstNameLabel" runat="server" Text='<%# Eval("FirstMidName") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>

在顯示模式中,兩 Label 個控制項會顯示名字和姓氏。 在編輯模式中,會提供兩個文字方塊,讓您可以變更名字和姓氏。 如同 Label 顯示模式中的控制項,您可以使用 BindEval 運算式,就像直接連接到資料庫的資料來源控制項 ASP.NET 一樣。 唯一的差異在於您要指定實體屬性,而不是資料庫資料行。

最後一個資料行是顯示註冊日期的範本欄位。 變更此欄位的標記,如下所示:

<asp:TemplateField HeaderText="Enrollment Date" SortExpression="EnrollmentDate">
                <EditItemTemplate>
                    <asp:TextBox ID="EnrollmentDateTextBox" runat="server" Text='<%# Bind("EnrollmentDate", "{0:d}") %>'></asp:TextBox>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:Label ID="EnrollmentDateLabel" runat="server" Text='<%# Eval("EnrollmentDate", "{0:d}") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>

在顯示和編輯模式中,格式字串 「{0,d}」 會導致日期以「簡短日期」格式顯示。 (您的電腦可能會設定為與本教學課程中顯示的螢幕影像不同顯示此格式。)

請注意,在上述每個範本欄位中,設計工具預設會使用 Bind 運算式,但您已將該運算式變更為 Eval 元素中的 ItemTemplate 運算式。 運算式 Bind 可讓您在控制項屬性中使用 GridView 資料,以防您需要存取程式碼中的資料。 在此頁面中,您不需要在程式碼中存取此資料,因此您可以使用 Eval 更有效率的 。 如需詳細資訊,請參閱 將資料從資料控制項取出

修改 EntityDataSource 控制項標記以改善效能

在 控制項的標記中 EntityDataSource ,移除 ConnectionStringDefaultContainerName 屬性,並將其取代為 ContextTypeName="ContosoUniversity.DAL.SchoolEntities" 屬性。 這是每次建立 EntityDataSource 控制項時應該所做的變更,除非您需要使用不同于物件內容類別別中硬式編碼的連接。 ContextTypeName使用 屬性可提供下列優點:

  • 效能較佳。 EntityDataSource當控制項使用 ConnectionStringDefaultContainerName 屬性初始化資料模型時,它會對每個要求執行額外的工作來載入中繼資料。 如果您指定 ContextTypeName 屬性,則不需要這樣做。
  • 預設會在產生的物件內容類別別中開啟延遲載入, (SchoolEntities 例如本教學課程) Entity Framework 4.0。 這表示當您需要時,導覽屬性會自動載入相關資料。 本教學課程稍後會更詳細地說明延遲載入。
  • 在此案例中,您已套用至物件內容類別別的任何自訂 (, SchoolEntities 類別) 將可供使用 控制項的 EntityDataSource 控制項使用。 自訂物件內容類別別是本教學課程系列未涵蓋的進階主題。 如需詳細資訊,請參閱 擴充 Entity Framework 產生的類型

標記現在會類似下列範例, (屬性的順序可能不同) :

<asp:EntityDataSource ID="StudentsEntityDataSource" runat="server"
        ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
        EntitySetName="People"
        EnableDelete="True" EnableUpdate="True">
    </asp:EntityDataSource>

屬性 EnableFlattening 是指舊版 Entity Framework 中所需的功能,因為外鍵資料行並未公開為實體屬性。 目前的版本可讓您使用 外鍵關聯,這表示外鍵屬性會公開給除了多對多關聯之外的所有關聯。 如果您的實體具有外鍵屬性且沒有 複雜類型,您可以將此屬性設定為 False 。 請勿從標記中移除 屬性,因為預設值為 True 。 如需詳細資訊,請參閱 將物件扁平化 (EntityDataSource)

執行頁面,您會看到學生和員工清單, (您將在下一個教學課程) 只篩選學生。 名字和姓氏會一起顯示。

Image07

若要排序顯示,請按一下資料行名稱。

按一下任何資料列中的 [編輯 ]。 文字方塊隨即顯示,您可以在其中變更名字和姓氏。

Image08

[ 刪除] 按鈕也可以運作。 針對具有註冊日期且資料列消失的資料列按一下 [刪除]。 (沒有註冊日期的資料列代表講師,您可能會收到參考完整性錯誤。在下一個教學課程中,您將篩選此清單,只包含 students.)

顯示導覽屬性中的資料

現在假設您想要知道每個學生註冊的課程數目。 Entity Framework 會在實體的 StudentGradesPerson 導覽屬性中提供該資訊。 因為資料庫設計不允許學生在課程中註冊,而不需要指派成績,所以在本教學課程中 StudentGrade ,您可以假設在與課程相關聯的資料表資料列中有一個資料列與在課程中註冊相同。 (導覽 Courses 屬性僅適用于 instructors.)

當您使用 ContextTypeName 控制項的 EntityDataSource 屬性時,Entity Framework 會在存取該屬性時自動擷取導覽屬性的資訊。 這稱為 延遲載入。 不過,這可能會沒有效率,因為它會在每次需要其他資訊時,對資料庫產生個別呼叫。 如果您需要控制項所傳回 EntityDataSource 之每個實體的導覽屬性資料,則擷取相關資料以及單一呼叫資料庫中的實體本身會更有效率。 這稱為 積極式載入,您可以藉由設定 Include 控制項的 屬性來指定導覽屬性的 EntityDataSource 積極式載入。

Students.aspx中,您想要顯示每位學生的課程數目,因此積極式載入是最佳選擇。 如果您顯示所有學生,但只針對其中幾個學生顯示課程數目, (這除了標記) 之外,還需要撰寫某些程式碼,則延遲載入可能是較佳的選擇。

開啟或切換至 Students.aspx、切換至 [設計] 檢視、選取 StudentsEntityDataSource ,然後在 [ 屬性 ] 視窗中,將 [包含 ] 屬性設定為 StudentGrades。 (如果您想要取得多個導覽屬性,您可以指定以逗號分隔的名稱,例如 StudentGrades、Courses.)

Image19

切換至 [來源 ] 檢視。 在 控制項中 StudentsGridView ,在最後一個專案 asp:TemplateField 之後,新增下列新範本欄位:

<asp:TemplateField HeaderText="Number of Courses">
                <ItemTemplate>
                    <asp:Label ID="Label1" runat="server" Text='<%# Eval("StudentGrades.Count") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>

在運算式中 Eval ,您可以參考導覽屬性 StudentGrades 。 因為這個屬性包含集合,所以它具有 Count 屬性,可讓您用來顯示註冊學生的課程數目。 在稍後的教學課程中,您將瞭解如何顯示包含單一實體而非集合之導覽屬性的資料。 (請注意,您無法使用 BoundField 元素來顯示導覽屬性中的資料。)

執行頁面,您現在會看到每個學生註冊的課程數目。

Internet Explorer 視窗的螢幕擷取畫面,其中顯示 [新增學生] 檢視,其中已填入文字欄位的 John Smith 名稱和註冊日期。

使用 DetailsView 控制項插入實體

下一個步驟是建立具有 DetailsView 控制項的頁面,讓您新增新學生。 關閉瀏覽器,然後使用 Site.Master 主版頁面建立新的網頁。 將 [ StudentsAdd.aspx] 頁面命名為 ,然後切換至 [來源 ] 檢視。

新增下列標記,以取代名為 Content2Content 控制項的現有標記:

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Add New Students</h2>
    <asp:EntityDataSource ID="StudentsEntityDataSource" runat="server"
        ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
        EnableInsert="True" EntitySetName="People">
    </asp:EntityDataSource>
    <asp:DetailsView ID="StudentsDetailsView" runat="server" 
        DataSourceID="StudentsEntityDataSource" AutoGenerateRows="False"
        DefaultMode="Insert">
        <Fields>
            <asp:BoundField DataField="FirstMidName" HeaderText="First Name" 
                SortExpression="FirstMidName" />
            <asp:BoundField DataField="LastName" HeaderText="Last Name" 
                SortExpression="LastName" />
            <asp:BoundField DataField="EnrollmentDate" HeaderText="Enrollment Date" 
                SortExpression="EnrollmentDate" />
             <asp:CommandField ShowInsertButton="True" />
       </Fields>
    </asp:DetailsView>
</asp:Content>

此標記會建立一個 EntityDataSource 控制項,類似于您在 Students.aspx中建立的控制項,但會啟用插入。 GridView和 控制項一樣,控制項的 DetailsView 系結欄位會與直接連接到資料庫的資料控制項一樣編碼,不同之處在于它們參考實體屬性。 在此情況下, DetailsView 控制項僅用於插入資料列,因此您已將預設模式設定為 Insert

執行頁面並新增學生。

Internet Explorer 視窗的螢幕擷取畫面,其中顯示 [新增學生] 檢視,其中已填入文字欄位的 John Smith 名稱和註冊日期。

插入新學生之後不會發生任何事,但如果您現在執行 Students.aspx,您會看到新的學生資訊。

在Drop-Down清單中顯示資料

在下列步驟中,您將使用 EntityDataSource 控制項將資料系結 DropDownList 至實體集。 在本教學課程的這個部分中,您不會對此清單執行太多動作。 不過,在後續部分中,您將使用清單讓使用者選取部門來顯示與部門相關聯的課程。

建立名為 Courses.aspx的新網頁。 在 [來源 ] 檢視中,將標題新增至 Content 名為 Content2 的控制項:

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Courses by Department</h2>
</asp:Content>

[設計 ] 檢視中,將控制項新增 EntityDataSource 至頁面,但這次將它命名為 DepartmentsEntityDataSource 除外。 選取 [Departments ] 作為 [EntitySetName ] 值,然後只選取 [DepartmentID ] 和 [ 名稱] 屬性。

Image15

[工具箱] 的 [標準] 索引標籤中,將控制項拖曳 DropDownList 至頁面,將它 DepartmentsDropDownList 命名為 ,按一下智慧標籤,然後選取 [選擇資料來源] 以啟動[資料來源設定精靈]。

Image16

在 [ 選擇資料來源 ] 步驟中,選取 [DepartmentsEntityDataSource ] 作為資料來源,按一下 [ 重新整理架構],然後選取 [ 名稱 ] 作為要顯示的資料欄位,並將 DepartmentID 顯示為值資料欄位。 按一下 [確定]。

Image17

您使用 Entity Framework 將資料系結控制項的方法與其他 ASP.NET 資料來源控制項相同,但您指定實體和實體屬性除外。

切換至 [來源 ] 檢視,並在控制項之前 DropDownList 立即新增 「選取部門:」。

Select a department:
    <asp:DropDownList ID="DropDownList1" runat="server" 
        DataSourceID="EntityDataSource1" DataTextField="Name" 
        DataValueField="DepartmentID">
    </asp:DropDownList>

提醒您,將 和 DefaultContainerName 屬性取代 ConnectionStringContextTypeName="ContosoUniversity.DAL.SchoolEntities" 屬性,以變更此時控制項的標記 EntityDataSource 。 在變更 EntityDataSource 控制項標記之前,最好等到建立與資料來源控制項連結的資料繫結控制項之後,因為在您進行變更之後,設計工具不會在資料繫結控制項中提供 [ 重新整理架構 ] 選項。

執行頁面,您可以從下拉式清單中選取部門。

Internet Explorer 瀏覽器視窗的螢幕擷取畫面,其中顯示 [依部門] 檢視的 [課程] 檢視,其中包含部門下拉式功能表。

這會完成使用 控制項的 EntityDataSource 簡介。 使用此控制項通常與使用其他 ASP.NET 資料來源控制項不同,不同之處在于參考實體和資料行,而不是資料表和資料行。 唯一的例外狀況是當您想要存取導覽屬性時。 在下一個教學課程中,您會看到搭配控制項使用的 EntityDataSource 語法可能也會與您篩選、分組和排序資料時的其他資料來源控制項不同。