演练:将一个实体映射到多个表

本主题演示如何通过修改实体数据模型 (EDM) 中的概念模型,而将一个实体类型映射到两个表。如果多个表共享同一个键,则可以将一个实体映射到这些表。适用于将一个实体类型映射到两个表的概念,可以轻松扩展为将一个实体类型映射到两个以上的表。有关将一个实体映射到多个表的更多信息,请参见如何:通过将单个实体映射到两个表以定义模型

在本演练中将通过修改 CourseManager 应用程序中使用的 EDM,而将一个实体类型映射到两个表(有关更多信息,请参见本主题稍后的“先决条件”一节。)您将创建一个新的实体类型(派生自 Person 实体类型的 Instructor),并将之映射到 PersonOfficeAssignment 表。下面的步骤概述了该过程(有关更多详细信息,请参见本文档稍后的过程):

  1. 创建新的实体类型 Instructor

  2. Instructor 的基类型设置为 Person

    Note注意

    为了将一个实体类型映射到多个表,不必创建继承层次结构。在本例中使用继承层次结构是为了更加贴近现实(在一所学校中,只有一名教师将会获得办公室分配)。不必创建 Instructor 实体类型,便可以将 Person 实体类型同时映射到 PersonOfficeAssignment 表。

  3. HireDate 属性从 Person 移到 Instructor

  4. Location 属性从 OfficeAssignment 移到 Instructor

  5. 按照 HireDate Is Not Null 条件将 Instructor 实体映射到 Person 表。将 HireDate 列映射到 HireDate 属性。

  6. 无条件将 Instructor 实体映射到 OfficeAssignment 表。将 InstructorID 列映射到 PersonID 属性,将 Location 列映射到 Location 属性。

  7. 删除 OfficeAssignment 实体类型。

系统必备

要完成本演练,必须生成 CourseManager 应用程序。有关更多信息,请参见实体框架快速入门。您将通过添加一个新的实体类型,并将之映射到两个表,而修改在 CourseManager 应用程序中使用的 EDM。然后,扩展应用程序的功能,以显示教师的办公室分配情况。

Note注意

因为本文档中的许多演练主题都使用该 CourseManager 应用程序作为起点,所以建议在本演练中使用 CourseManager 应用程序的副本,而不要编辑原始 CourseManager 代码。

此演练假定读者对于 Visual Studio、.NET Framework 以及使用 Visual C# 或 Visual Basic 编程具有基本的了解。

将一个实体映射到两个表

在下面的过程中,您将通过创建新的实体类型 (Instructor),并将之映射到两个表(PersonOfficeAssignment),而修改 SchoolModel EDM 的概念部分。

将一个实体映射到两个表

  1. 在 Visual Studio 中打开 CourseManager 解决方案。

  2. 在解决方案资源管理器中,双击 School.edmx 文件。

    School.edmx 文件在实体数据模型设计器(实体设计器)中打开。

  3. 右键单击实体设计器设计图面的空白区域,指向**“添加”,然后单击“实体”**。

    出现**“新建实体”**对话框。

  4. 对于**“实体名称”请键入 Instructor,然后从“基类型”**下拉列表中选择 Person

  5. 单击**“确定”**。

    新的实体类型创建完毕,并且显示在设计图面上。

  6. 右键单击 Person 实体类型的 HireDate 属性(在**“标量属性”下面),然后选择“剪切”**。

  7. 右键单击 Instructor 实体类型的**“标量属性”,然后选择“粘帖”**。

  8. 右键单击 HireDate 属性,然后选择**“属性”**。

    出现**“属性”**窗口。

  9. 在**“属性”窗口中,将“可以为 Null”**属性设置为 false

  10. 右键单击 OfficeAssignment 实体类型的 Location 属性,然后选择**“剪切”**。

  11. 右键单击 Instructor 实体类型的**“标量属性”,然后选择“粘帖”**。

  12. 右键单击 Location 属性,然后选择**“属性”**。

  13. 在**“属性”窗口中,将“可以为 Null”**属性设置为 false

  14. 对于 OfficeAssignment 类型的 Timestamp 属性重复步骤 10 到 13。

    Note注意

    下一步骤要求使用“映射详细信息”窗口。如果没有出现此窗口,请右键单击设计图面,然后选择“映射详细信息”

  15. 选择 Instructor 实体类型,然后单击**“映射详细信息”窗口中的“<添加表或视图>”**。

    **“<添加表或视图>”**字段变成下拉列表,其中包含选定实体可映射到的表或视图。

  16. 从下拉列表中选择 Person

    **“映射详细信息”**窗口将会根据默认列映射以及一个关于添加条件的选项而进行更新。

  17. 单击**“<添加条件>”**。

    **“<添加条件>”**字段变成一个包含列的下拉列表(可为其中各列设置条件)。

  18. 从下拉列表中选择 HireDate

  19. 在**“映射详细信息”窗口的“运算符”列中,从下拉列表中选择“Is”**。

  20. 在**“映射详细信息”窗口的“属性/值”列中,选择“Not Null”**。

  21. 单击**“<添加表或视图>”**,然后从下拉列表中选择 OfficeAssignment

    **“映射详细信息”**窗口将会根据默认的列映射进行更新。

  22. 单击对应于 InstructorID 列的**“属性/值”**字段,然后从下拉列表中选择 PersonID

  23. 右键单击 OfficeAssignment 实体类型,然后选择**“删除”**。

Instructor 实体类型现在已经映射到 PersonOfficeAssignment 表。

构造用户界面

接下来,将向 CourseViewer 窗体添加一个用于加载和显示 CourseAssignmentForm 窗体的按钮。然后,将用于显示 Instructor 办公室位置的 DataGridView 控件添加到窗体中。最后,向 CourseAssignmentForm 窗体添加一个将更新保存到数据库中的按钮。

构造用户界面

  1. 在**“解决方案资源管理器”中右键单击 CourseManager 项目,指向“添加”,然后选择“新建项”**。

    出现**“添加新项”**对话框。

  2. 选择**“Windows 窗体”,将窗体的名称设置为 OfficeAssignment.vb 或 OfficeAssignment.cs,然后单击“添加”**。

    新窗体即被添加到项目中,并在窗体设计器中打开。该窗体的名称设置为 OfficeAssignment,文本设置为 OfficeAssignment

  3. DataGridView 控件拖入窗体,然后将其名称设置为 officeGridView

  4. 单击 DataGridView 的智能标记,然后清除**“启用添加”“启用删除”**选项。

  5. Button 控件拖入窗体,然后将其名称属性设置为 saveChanges,并将其文本属性设置为 Update

  6. 在**“解决方案资源管理器”**中,双击 CourseViewer.csCourseViewer.vb

    出现 CourseViewer 窗体的设计视图。

  7. 从工具箱将 Button 控件拖入 CourseViewer 窗体。

  8. 在**“属性”**窗口中,将按钮的名称设置为 viewOffices,然后将按钮的文本设置为 View Offices

  9. 双击 viewOfficesButton

    CourseViewer 的代码隐藏文件打开。

  10. 将下面的代码添加到 viewOffices_click 事件处理程序中:

    Dim officeForm As New OfficeAssignment()
    officeForm.Visible = True
    
    OfficeAssignment officeForm = new OfficeAssignment();
    officeForm.Visible = true;
    

现在,就完成了此窗体的用户界面。

查询 EDM

此应用程序通过将 DataGridView 控件绑定到 SchoolModel EDM 而显示数据。允许编辑显示在 DataGridView 控件中的信息,并且可以将更改保存到数据库中。有关将对象绑定到控件的更多信息,请参见将对象绑定到控件(实体框架)

查询 EDM

  1. 在窗体设计器中打开 OfficeAssignment 窗体之后,请双击窗体主体。

    OfficeAssignment 窗体的代码隐藏文件打开。

  2. 添加以下 using (C#) 或 Imports (Visual Basic) 语句,以引用基于 School 数据库和实体命名空间创建的模型。

    Imports System.Data.Objects
    Imports System.Data.Objects.DataClasses
    
    using System.Data.Objects;
    using System.Data.Objects.DataClasses;
    
  3. 将表示数据上下文的属性添加到 OfficeAssignment 类中:

    ' Create an ObjectContext instance based on SchoolEntity.
    Private schoolContext As SchoolEntities
    
    // Create an ObjectContext instance based on SchoolEntity.
    private SchoolEntities schoolContext;
    
  4. 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;
    
  5. 返回 OfficeAssignment 窗体的设计视图,然后双击 saveChangesButton 控件。

    saveChanges_Click 事件处理程序在代码隐藏文件中创建。

  6. 在事件处理程序中添加代码,从而将曾在 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();
        }
    }
}

后续步骤

您已成功将一个实体映射到多个表。有关如何创建一个实体映射到多个表的模型的更多信息,请参见如何:通过将单个实体映射到两个表以定义模型。有关如何生成使用实体框架的应用程序的更多信息,请参见编程指南(实体框架)

另请参见

其他资源

ADO.NET 实体数据模型设计器方案
实体数据模型工具任务