本主题演示如何通过修改实体数据模型 (EDM) 中的概念模型,而将一个实体类型映射到两个表。如果多个表共享同一个键,则可以将一个实体映射到这些表。适用于将一个实体类型映射到两个表的概念,可以轻松扩展为将一个实体类型映射到两个以上的表。有关将一个实体映射到多个表的更多信息,请参见如何:通过将单个实体映射到两个表以定义模型。
在本演练中将通过修改 CourseManager 应用程序中使用的 EDM,而将一个实体类型映射到两个表(有关更多信息,请参见本主题稍后的“先决条件”一节。)您将创建一个新的实体类型(派生自 Person 实体类型的 Instructor),并将之映射到 Person 和 OfficeAssignment 表。下面的步骤概述了该过程(有关更多详细信息,请参见本文档稍后的过程):
- 创建新的实体类型 Instructor。 
- 将 Instructor 的基类型设置为 Person。 .gif) 注意 注意- 为了将一个实体类型映射到多个表,不必创建继承层次结构。在本例中使用继承层次结构是为了更加贴近现实(在一所学校中,只有一名教师将会获得办公室分配)。不必创建 Instructor 实体类型,便可以将 Person 实体类型同时映射到 Person 和 OfficeAssignment 表。 
- 将 HireDate 属性从 Person 移到 Instructor。 
- 将 Location 属性从 OfficeAssignment 移到 Instructor。 
- 按照 HireDate Is Not Null 条件将 Instructor 实体映射到 Person 表。将 HireDate 列映射到 HireDate 属性。 
- 无条件将 Instructor 实体映射到 OfficeAssignment 表。将 InstructorID 列映射到 PersonID 属性,将 Location 列映射到 Location 属性。 
- 删除 OfficeAssignment 实体类型。 
系统必备
要完成本演练,必须生成 CourseManager 应用程序。有关更多信息,请参见实体框架快速入门。您将通过添加一个新的实体类型,并将之映射到两个表,而修改在 CourseManager 应用程序中使用的 EDM。然后,扩展应用程序的功能,以显示教师的办公室分配情况。
| .gif) 注意 | 
|---|
| 因为本文档中的许多演练主题都使用该 CourseManager 应用程序作为起点,所以建议在本演练中使用 CourseManager 应用程序的副本,而不要编辑原始 CourseManager 代码。 | 
此演练假定读者对于 Visual Studio、.NET Framework 以及使用 Visual C# 或 Visual Basic 编程具有基本的了解。
将一个实体映射到两个表
在下面的过程中,您将通过创建新的实体类型 (Instructor),并将之映射到两个表(Person 和 OfficeAssignment),而修改 SchoolModel EDM 的概念部分。
将一个实体映射到两个表
- 在 Visual Studio 中打开 CourseManager 解决方案。 
- 在解决方案资源管理器中,双击 School.edmx 文件。 - School.edmx 文件在实体数据模型设计器(实体设计器)中打开。 
- 右键单击实体设计器设计图面的空白区域,指向**“添加”,然后单击“实体”**。 - 出现**“新建实体”**对话框。 
- 对于**“实体名称”请键入 Instructor,然后从“基类型”**下拉列表中选择 Person。 
- 单击**“确定”**。 - 新的实体类型创建完毕,并且显示在设计图面上。 
- 右键单击 Person 实体类型的 HireDate 属性(在**“标量属性”下面),然后选择“剪切”**。 
- 右键单击 Instructor 实体类型的**“标量属性”,然后选择“粘帖”**。 
- 右键单击 HireDate 属性,然后选择**“属性”**。 - 出现**“属性”**窗口。 
- 在**“属性”窗口中,将“可以为 Null”**属性设置为 false。 
- 右键单击 OfficeAssignment 实体类型的 Location 属性,然后选择**“剪切”**。 
- 右键单击 Instructor 实体类型的**“标量属性”,然后选择“粘帖”**。 
- 右键单击 Location 属性,然后选择**“属性”**。 
- 在**“属性”窗口中,将“可以为 Null”**属性设置为 false。 
- 对于 OfficeAssignment 类型的 Timestamp 属性重复步骤 10 到 13。 .gif) 注意 注意- 下一步骤要求使用“映射详细信息”窗口。如果没有出现此窗口,请右键单击设计图面,然后选择“映射详细信息”。 
- 选择 Instructor 实体类型,然后单击**“映射详细信息”窗口中的“<添加表或视图>”**。 - **“<添加表或视图>”**字段变成下拉列表,其中包含选定实体可映射到的表或视图。 
- 从下拉列表中选择 Person。 - **“映射详细信息”**窗口将会根据默认列映射以及一个关于添加条件的选项而进行更新。 
- 单击**“<添加条件>”**。 - **“<添加条件>”**字段变成一个包含列的下拉列表(可为其中各列设置条件)。 
- 从下拉列表中选择 HireDate。 
- 在**“映射详细信息”窗口的“运算符”列中,从下拉列表中选择“Is”**。 
- 在**“映射详细信息”窗口的“属性/值”列中,选择“Not Null”**。 
- 单击**“<添加表或视图>”**,然后从下拉列表中选择 OfficeAssignment。 - **“映射详细信息”**窗口将会根据默认的列映射进行更新。 
- 单击对应于 InstructorID 列的**“属性/值”**字段,然后从下拉列表中选择 PersonID。 
- 右键单击 OfficeAssignment 实体类型,然后选择**“删除”**。 
Instructor 实体类型现在已经映射到 Person 和 OfficeAssignment 表。
构造用户界面
接下来,将向 CourseViewer 窗体添加一个用于加载和显示 CourseAssignmentForm 窗体的按钮。然后,将用于显示 Instructor 办公室位置的 DataGridView 控件添加到窗体中。最后,向 CourseAssignmentForm 窗体添加一个将更新保存到数据库中的按钮。
构造用户界面
- 在**“解决方案资源管理器”中右键单击 CourseManager 项目,指向“添加”,然后选择“新建项”**。 - 出现**“添加新项”**对话框。 
- 选择**“Windows 窗体”,将窗体的名称设置为 OfficeAssignment.vb 或 OfficeAssignment.cs,然后单击“添加”**。 - 新窗体即被添加到项目中,并在窗体设计器中打开。该窗体的名称设置为 OfficeAssignment,文本设置为 OfficeAssignment。 
- 将 DataGridView 控件拖入窗体,然后将其名称设置为 officeGridView。 
- 单击 DataGridView 的智能标记,然后清除**“启用添加”和“启用删除”**选项。 
- 将 Button 控件拖入窗体,然后将其名称属性设置为 saveChanges,并将其文本属性设置为 Update。 
- 在**“解决方案资源管理器”**中,双击 CourseViewer.cs 或 CourseViewer.vb。 - 出现 CourseViewer 窗体的设计视图。 
- 从工具箱将 Button 控件拖入 CourseViewer 窗体。 
- 在**“属性”**窗口中,将按钮的名称设置为 viewOffices,然后将按钮的文本设置为 View Offices。 
- 双击 viewOfficesButton。 - CourseViewer 的代码隐藏文件打开。 
- 将下面的代码添加到 viewOffices_click 事件处理程序中: - Dim officeForm As New OfficeAssignment() officeForm.Visible = True- OfficeAssignment officeForm = new OfficeAssignment(); officeForm.Visible = true;
现在,就完成了此窗体的用户界面。
查询 EDM
此应用程序通过将 DataGridView 控件绑定到 SchoolModel EDM 而显示数据。允许编辑显示在 DataGridView 控件中的信息,并且可以将更改保存到数据库中。有关将对象绑定到控件的更多信息,请参见将对象绑定到控件(实体框架)。
查询 EDM
- 在窗体设计器中打开 OfficeAssignment 窗体之后,请双击窗体主体。 - OfficeAssignment 窗体的代码隐藏文件打开。 
- 添加以下 using (C#) 或 Imports (Visual Basic) 语句,以引用基于 School 数据库和实体命名空间创建的模型。 - Imports System.Data.Objects Imports System.Data.Objects.DataClasses- using System.Data.Objects; using System.Data.Objects.DataClasses;
- 将表示数据上下文的属性添加到 OfficeAssignment 类中: - ' Create an ObjectContext instance based on SchoolEntity. Private schoolContext As SchoolEntities- // Create an ObjectContext instance based on SchoolEntity. private SchoolEntities schoolContext;
- 在 OfficeAssignment_Load 事件处理程序中,添加代码以初始化对象上下文并将 DataGridView 控件绑定到返回 Instructor 信息的查询。 - ' Initialize the ObjectContext. schoolContext = New SchoolEntities() ' Get Persons of type Instructor. Dim instructorQuery As ObjectQuery(Of Instructor) = _ schoolContext.Person.OfType(Of Instructor)() ' Bind the query results to the GridView control. ' Display only location and name. officeGridView.DataSource = instructorQuery _ .Execute(MergeOption.OverwriteChanges) officeGridView.Columns("HireDate").Visible = False officeGridView.Columns("PersonID").Visible = False officeGridView.Columns("Timestamp").Visible = False officeGridView.Columns("EnrollmentDate").Visible = False- schoolContext = new SchoolEntities(); // Get Persons of type Instructor. ObjectQuery<Instructor> instructorQuery = schoolContext .Person.OfType<Instructor>(); // Bind the query results to the GridView control. // Display only location and name. officeGridView.DataSource = instructorQuery .Execute(MergeOption.OverwriteChanges); officeGridView.Columns["HireDate"].Visible = false; officeGridView.Columns["Timestamp"].Visible = false; officeGridView.Columns["PersonID"].Visible = false; officeGridView.Columns["EnrollmentDate"].Visible = false;
- 返回 OfficeAssignment 窗体的设计视图,然后双击 saveChangesButton 控件。 - saveChanges_Click 事件处理程序在代码隐藏文件中创建。 
- 在事件处理程序中添加代码,从而将曾在 DataGridView 控件中所做的所有更改保存到数据库中。 - Dim numChanges As Integer ' Save object changes to the database, display a message, ' and refresh the form. numChanges = schoolContext.SaveChanges() MessageBox.Show(numChanges.ToString() + _ " change(s) saved to the database.") Me.Refresh()- int numChanges; // Save object changes to the database, display a message, // and refresh the form. numChanges = schoolContext.SaveChanges(); MessageBox.Show(numChanges.ToString() + " change(s) saved to the database."); this.Refresh();
现在,就完成了应用程序。按 Ctrl+F5 运行应用程序。单击 View Offices 按钮以加载 OfficeAssignments 窗体。出现教师姓名和办公室位置。允许编辑显示出来的信息,并且可以通过单击 Update 按钮而将更改保存到数据库中。
代码清单
本节列出了 OfficeAssignmentForm 窗体的代码隐藏文件的最终版本。
Imports System.Data.Objects
Imports System.Data.Objects.DataClasses
Public Class OfficeAssignment
    ' Create an ObjectContext instance based on SchoolEntity.
    Private schoolContext As SchoolEntities
    Private Sub OfficeAssignment_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' Initialize the ObjectContext.
        schoolContext = New SchoolEntities()
        ' Get Persons of type Instructor.
        Dim instructorQuery As ObjectQuery(Of Instructor) = _
            schoolContext.Person.OfType(Of Instructor)()
        ' Bind the query results to the GridView control.
        ' Display only location and name.
        officeGridView.DataSource = instructorQuery _
            .Execute(MergeOption.OverwriteChanges)
        officeGridView.Columns("HireDate").Visible = False
        officeGridView.Columns("PersonID").Visible = False
        officeGridView.Columns("Timestamp").Visible = False
        officeGridView.Columns("EnrollmentDate").Visible = False
    End Sub
    Private Sub saveChanges_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles saveChanges.Click
        Dim numChanges As Integer
        ' Save object changes to the database, display a message,
        ' and refresh the form.
        numChanges = schoolContext.SaveChanges()
        MessageBox.Show(numChanges.ToString() + _
                        " change(s) saved to the database.")
        Me.Refresh()
    End Sub
End Class
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
namespace CourseManager
{
    public partial class OfficeAssignment : Form
    {
        // Create an ObjectContext instance based on SchoolEntity.
        private SchoolEntities schoolContext;
        public OfficeAssignment()
        {
            InitializeComponent();
        }
        private void OfficeAssignment_Load(object sender, EventArgs e)
        {
            schoolContext = new SchoolEntities();
            // Get Persons of type Instructor.
            ObjectQuery<Instructor> instructorQuery = schoolContext
                .Person.OfType<Instructor>();
            // Bind the query results to the GridView control.
            // Display only location and name.
            officeGridView.DataSource = instructorQuery
                .Execute(MergeOption.OverwriteChanges);
            officeGridView.Columns["HireDate"].Visible = false;
            officeGridView.Columns["Timestamp"].Visible = false;
            officeGridView.Columns["PersonID"].Visible = false;
            officeGridView.Columns["EnrollmentDate"].Visible = false;
        }
        private void saveChanges_Click(object sender, EventArgs e)
        {
            int numChanges;
            // Save object changes to the database, display a message,
            // and refresh the form.
            numChanges = schoolContext.SaveChanges();
            MessageBox.Show(numChanges.ToString() +
                " change(s) saved to the database.");
            this.Refresh();
        }
    }
}
后续步骤
您已成功将一个实体映射到多个表。有关如何创建一个实体映射到多个表的模型的更多信息,请参见如何:通过将单个实体映射到两个表以定义模型。有关如何生成使用实体框架的应用程序的更多信息,请参见编程指南(实体框架)。