演练:将一个实体映射到多个表(实体数据模型工具)

本主题介绍如何通过修改概念模型将一个实体类型映射到两个表。 如果多个表共享同一个公共键,则可以将一个实体映射到这些表。 适用于将一个实体类型映射到两个表的概念,可以轻松扩展为将一个实体类型映射到两个以上的表。

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

  1. 创建新的实体类型 Instructor

  2. Instructor 的基类型设置为 Person

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

  3. HireDate 属性从 Person 移到 Instructor

  4. LocationTimestamp 属性从 OfficeAssignment 移到 Instructor

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

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

  7. 删除 OfficeAssignment 实体类型。

必备条件

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

Cc716698.note(zh-cn,VS.100).gif注意:
因为本文档中的许多演练主题都使用该 CourseManager 应用程序作为起点,所以建议在本演练中使用 CourseManager 应用程序的副本,而不要编辑原始 CourseManager 代码。

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

将一个实体映射到两个表

在此过程中,您将通过创建一个新的实体类型 (Instructor) 并将该类型映射到两个表(PersonOfficeAssignment)来修改 School.edmx 文件的 CSDL 和映射内容。

将一个实体映射到两个表

  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。

    Cc716698.note(zh-cn,VS.100).gif注意:
    下一步骤要求使用“映射详细信息”窗口。如果没有出现此窗口,请右键单击设计图面,然后选择“映射详细信息”

  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. 双击 viewOffices Button

    CourseViewer 的代码隐藏文件打开。

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

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

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

查询概念模型

此应用程序通过将 DataGridView 控件绑定到查询来显示数据。 允许编辑显示在 DataGridView 控件中的信息,并且可以将更改保存到数据库中。 有关将对象绑定到控件的更多信息,请参见Binding Objects to Controls (Entity Framework)

查询概念模型

  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.People.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
    officeGridView.Columns("StudentGrades").Visible = False
    officeGridView.Columns("Courses").Visible = False
    
    schoolContext = new SchoolEntities();
    
    // Get Persons of type Instructor.
    ObjectQuery<Instructor> instructorQuery = schoolContext
        .People.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;
    officeGridView.Columns["StudentGrades"].Visible = false;
    officeGridView.Columns["Courses"].Visible = false;
    
  5. 返回 OfficeAssignment 窗体的设计视图,然后双击 saveChanges Button 控件。

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

  6. 在事件处理程序中添加代码,从而将曾在 DataGridView 控件中所做的所有更改保存到数据库中。

    ' Save object changes to the database, 
    ' display a message, and refresh the form.
    schoolContext.SaveChanges()
    MessageBox.Show("Change(s) saved to the database.")
    Me.Refresh()
    
    // Save object changes to the database, 
    // display a message, and refresh the form.
    schoolContext.SaveChanges();
    MessageBox.Show("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.People.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
        officeGridView.Columns("StudentGrades").Visible = False
        officeGridView.Columns("Courses").Visible = False
    End Sub

    Private Sub saveChanges_Click(ByVal sender As System.Object, _
                                  ByVal e As System.EventArgs) _
                                  Handles saveChanges.Click
        ' Save object changes to the database, 
        ' display a message, and refresh the form.
        schoolContext.SaveChanges()
        MessageBox.Show("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
                .People.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;
            officeGridView.Columns["StudentGrades"].Visible = false;
            officeGridView.Columns["Courses"].Visible = false;
        }

        private void saveChanges_Click(object sender, EventArgs e)
        {
            // Save object changes to the database, 
            // display a message, and refresh the form.
            schoolContext.SaveChanges();
            MessageBox.Show("Change(s) saved to the database.");
            this.Refresh();
        }
    }
}

后续步骤

您已成功将一个实体映射到多个表。 有关如何创建一个实体映射到多个表的模型的更多信息,请参见How to: Define a Model with a Single Entity Mapped to Two Tables。 有关如何生成使用实体框架的应用程序的更多信息,请参见ADO.NET Entity Framework

另请参见

其他资源

实体数据模型工具方案
实体数据模型工具任务