作者 :Tom Dykstra
Contoso University 範例 Web 應用程式示範如何使用 Entity Framework 4.0 和 Visual Studio 2010 建立 ASP.NET Web Forms應用程式。 如需教學課程系列的相關資訊,請參閱系列中的第一個教學課程
使用相關資料,繼續
在上一個教學課程中,您已開始使用 EntityDataSource 控制項來處理相關資料。 您已在導覽屬性中顯示多個階層層級和編輯的資料。 在本教學課程中,您將藉由新增和刪除關聯性,以及新增與現有實體有關聯性的新實體,繼續處理相關資料。
您將建立一個頁面,以新增指派給部門的課程。 部門已經存在,而且當您建立新課程時,您會同時建立其與現有部門之間的關聯性。
您也會建立一個頁面,將講師指派給課程,以使用多對多關聯性, (新增您選取) 兩個實體之間的關聯性,或從課程中移除講師, (移除您選取) 兩個實體之間的關聯性。 在資料庫中,新增講師與課程之間的關聯性會導致將新的資料列新增至 CourseInstructor 關聯資料表;移除關聯性牽涉到從 CourseInstructor 關聯資料表中刪除資料列。 不過,您可以在 Entity Framework 中設定導覽屬性來執行這項操作,而不需明確參考 CourseInstructor 資料表。
將具有關聯性的實體新增至現有實體
建立名為CoursesAdd.aspx的新網頁,其使用Site.Master 主版頁面,並將下列標記新增至名為 Content2 的 Content 控制項:
<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>
此標記會建立控制項 EntityDataSource ,以選取課程、啟用插入,以及指定事件的處理常式 Inserting 。 建立新 Course 實體時,您將使用 處理常式來更新 Department 導覽屬性。
標記也會建立 DetailsView 控制項,以用於新增 Course 實體。 標記會針對 Course 實體屬性使用系結欄位。 您必須輸入值, CourseID 因為這是系統產生的識別碼欄位。 相反地,這是必須在建立課程時手動指定的課程編號。
您可以使用導覽屬性的範本欄位, Department 因為導覽屬性不能與控制項搭配 BoundField 使用。 範本欄位提供下拉式清單來選取部門。 下拉式清單會使用 Eval 系 Bind 結至 Departments 實體集,而不是 再次系結,因為您無法直接系結導覽屬性以更新它們。 您可以指定控制項 Init 事件的處理常式 DropDownList ,以便儲存控制項的參考,以供更新 DepartmentID 外鍵的程式碼使用。
在 CoursesAdd.aspx.cs 的部分類別宣告之後,新增類別欄位來保存控制項的 DepartmentsDropDownList 參考:
private DropDownList departmentDropDownList;
新增 控制項 Init 事件的處理常式 DepartmentsDropDownList ,以便儲存控制項的參考。 這可讓您取得使用者輸入的值,並用它來更新 DepartmentID 實體的值 Course 。
protected void DepartmentsDropDownList_Init(object sender, EventArgs e)
{
departmentDropDownList = sender as DropDownList;
}
新增 控制項 Inserting 事件的處理常式 DetailsView :
protected void CoursesDetailsView_ItemInserting(object sender, DetailsViewInsertEventArgs e)
{
var departmentID = Convert.ToInt32(departmentDropDownList.SelectedValue);
e.Values["DepartmentID"] = departmentID;
}
當使用者按一下 Insert 時, Inserting 會在插入新記錄之前引發 事件。 處理常式中的程式碼會從 控制項取得 DepartmentID ,並使用它來設定將用於 DepartmentID 實體屬性的值 Course 。 DropDownList
Entity Framework 會負責將此課程新增至 Courses 相關聯 Department 實體的導覽屬性。 它也會將部門新增至 Department 實體的 Course 導覽屬性。
執行頁面。
輸入識別碼、標題、點數,然後選取部門,然後按一下 [ 插入]。
執行 Courses.aspx 頁面,然後選取相同的部門以查看新課程。
使用多對多關聯性
實體集與 People 實體集之間的 Courses 關聯性是多對多關聯性。
Course實體具有名為 People 的導覽屬性,可以包含零、一或多個相關 Person 實體, (代表指派給該課程的講師) 。
Person而且實體具有名為 Courses 的導覽屬性,該屬性可以包含零、一或多個相關 Course 實體 (代表講師指派給教學) 的課程。 一位講師可能會教導多個課程,而一個課程可能由多個講師教授。 在逐步解說的本節中,您將藉由更新相關實體的導覽屬性,來新增和移除 和 Course 實體之間的 Person 關聯性。
建立名為InstructorsCourses.aspx的新網頁,以使用Site.Master 主版頁面,並將下列標記新增至名為 Content2 的 Content 控制項:
<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>
此標記會建立控制項 EntityDataSource ,以擷取講師的名稱和 PersonIDPerson 實體。 控制項 DropDrownList 系結至 EntityDataSource 控制項。 控制項 DropDownList 會指定 事件的處理常式 DataBound 。 您將使用此處理程式來資料系結顯示課程的兩個下拉式清單。
標記也會建立下列控制項群組,以用於將課程指派給選取的講師:
-
DropDownList用於選取要指派課程的控制項。 此控制項會填入目前未指派給所選講師的課程。 - 起始
Button指派的控制項。 - 如果
Label指派失敗,顯示錯誤訊息的控制項。
最後,標記也會建立一組控制項,以用來從選取的講師中移除課程。
在 InstructorsCourses.aspx.cs中,新增 using 語句:
using ContosoUniversity.DAL;
新增方法,以填入顯示課程的兩個下拉式清單:
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;
}
}
此程式碼會從 Courses 實體集取得所有課程,並從所選講師實體的 Person 導覽屬性取得課程 Courses 。 然後,它會決定指派給該講師的課程,並據以填入下拉式清單。
新增按鈕 Click 事件的處理常式 Assign :
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;
}
}
此程式碼會 Person 取得所選講師的實體、取得 Course 所選課程的實體,並將選取的課程新增至 Courses 講師 Person 實體的導覽屬性。 然後,它會儲存資料庫的變更,並重新填入下拉式清單,以便立即看到結果。
新增按鈕 Click 事件的處理常式 Remove :
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;
}
}
此程式碼會取得 Person 所選講師的實體、取得 Course 所選課程的實體,並從實體的 Courses 導覽屬性中移除選取 Person 的課程。 然後,它會儲存資料庫的變更,並重新填入下拉式清單,以便立即看到結果。
將程式碼新增至 Page_Load 方法,以確保在沒有報告錯誤時看不到錯誤訊息,並針對講師下拉式清單的 和 SelectedIndexChanged 事件新增處理常式 DataBound ,以填入課程下拉式清單:
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();
}
執行頁面。
選取講師。 [ 指派課程 ] 下拉式清單會顯示講師未教授的課程,而 [移除課程 ] 下拉式清單會顯示講師已指派的課程。 在 [ 指派課程] 區段中,選取課程,然後按一下 [ 指派]。 課程會移至 [ 移除課程] 下拉式清單。 在 [ 移除課程 ] 區段中選取課程,然後按一下 [ 移除]。 課程會移至 [指派課程] 下拉式清單。
您現在已看到一些更多使用相關資料的方式。 在下列教學課程中,您將瞭解如何在資料模型中使用繼承,以改善應用程式的可維護性。