演练:使用外键属性添加实体(实体框架)

本主题介绍如何生成将外键公开为实体属性的概念模型以及如何编写用于创建实体和关系的代码。

从 Visual Studio 2010 开始,根据现有数据库生成模型时,ADO.NET 实体数据模型设计器(实体设计器)会在实体类型上创建与数据库中的外键列对应的标量属性。 可以使用外键属性创建和修改实体类型之间的关系。 默认情况下,实体设计器还会在实体类型上生成可用于创建和修改关系的导航属性。 本演练演示如何使用外键属性和导航属性来创建关系。 使用外键属性创建和管理关系可简化很多常用方案。 例如,通过使用外键属性创建和管理关系可以简化数据绑定、并发控制和 n 层方案。 有关更多信息,请参见Defining and Managing Relationships

必备条件

若要完成本演练,必须在计算机上安装 Visual Studio 2010 或更高版本,并且必须可以访问包含 School 示例数据库的 SQL Server 实例。 有关更多信息,请参见Creating the School Sample Database

本演练假设您对于 Visual Studio、.NET Framework 以及 Visual C# 或 Visual Basic 编程具有基本的了解和使用能力。

生成 .edmx 文件

若要完成此过程,必须在 Visual Studio 中打开一个新的 WPF 应用程序项目。 在此过程中,您将基于 School 示例数据库中的两个表生成一个 .edmx 文件。 .edmx 文件包含概念模型、存储模型以及两者之间的映射。 有关更多信息,请参见 .edmx 文件概述(实体框架)。 生成的概念模型中的实体类型将具有与数据库中的外键列对应的标量属性。

生成 .edmx 文件

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

    此时将显示**“添加新项”**对话框。

  2. 选择**“ADO.NET 实体数据模型”,然后单击“添加”。 (为了减少可见模板的数量,请选择“已安装的模板”下的“数据”**。)

  3. 实体数据模型向导中,选择**“从数据库生成”,然后单击“下一步”**。

  4. “选择您的数据连接”对话框中,连接到 School 示例数据库,然后单击**“下一步”**。

  5. “选择数据库对象”对话框中,展开**“表”节点,然后选择 CourseDepartment 表。 请注意,默认情况下,“确定所生成对象名称的单复数形式”“在模型中加入外键列”复选框处于选中状态。 如果保留选中“在模型中加入外键列”**复选框,将会在实体类型上创建映射到数据库中的外键列的标量属性,并且在实体之间创建外键关联。 清除此复选框将导致在实体类型之间创建独立关联。 有关更多信息,请参见 Association Element (CSDL)ReferentialConstraint Element (CSDL)

    如果保留选中**“确定所生成对象名称的单复数形式”**复选框,将会对实体集、实体类型以及导航属性名称应用英语语言的单复数规则。 有关更多信息,请参见“选择数据库对象”对话框(实体数据模型向导)

    本演练假定您在选中这两个复选框的情况下继续执行操作。

  6. 单击**“完成”**。

    此时会向项目中添加一个 .edmx 文件并且实体设计器中会显示该文件。 显示中包括两个实体类型(DepartmentCourse),这两个类型之间存在一对多 (1:*) 关联。 该关联是使用引用约束创建的,因此可以通过在 XML 编辑器中打开 .edmx 文件来查看该关联:

    <Association Name="FK_Course_Department">
      <End Role="Department" Type="SchoolModel.Department" Multiplicity="1" />
      <End Role="Course" Type="SchoolModel.Course" Multiplicity="*" />
      <ReferentialConstraint>
        <Principal Role="Department">
          <PropertyRef Name="DepartmentID" />
        </Principal>
        <Dependent Role="Course">
          <PropertyRef Name="DepartmentID" />
        </Dependent>
      </ReferentialConstraint>
    </Association>
    

    有关更多信息,请参见 ReferentialConstraint Element (CSDL)

创建用户界面

在此过程中,向应用程序中添加允许创建和更新有关系和课程的信息的控件。

创建用户界面

  1. 从 Visual Studio 的**“数据”菜单中,选择“显示数据源”**。

    此时将显示**“数据源”**窗格。

  2. 单击 MainWindow.xaml 选项卡以显示**“MainWindow”**设计图面。

  3. 在**“数据源”窗格中,单击“Courses”(课程)数据源,然后从下拉列表中选择“详细信息”**。

  4. 对**“Departments”(系)**数据源重复步骤 2。

  5. 在**“数据源”窗格中,展开 Courses 数据源,单击 DepartmentID 字段,然后选择“无”**。

  6. 在**“数据源”窗格中,展开 Departments 数据源,单击 Name 字段,然后选择“组合框”**。

  7. CoursesDepartments 数据源拖到**“MainWindow”**设计图面上。

    此时将在**“MainWindow”设计图面上为 CoursesDepartments 数据源创建“Grid”**控件。

  8. 在**“属性”窗口中清除 Department IDBudgetStart DateAdministrator 文本框的“IsEnabled”**复选框。

  9. 在“属性”窗口中选中 Name 组合框的**“IsEditable”**复选框。

  10. 从**“工具箱”中,将一个“Checkbox”控件拖到“MainWindow”设计图面上。 将“Checkbox”控件的名称改为 newDepartment,并将其“内容”**属性设置为 New Department

  11. 从**“工具箱”中,将一个“Button”控件拖到“MainWindow”设计图面上。 将“Button”控件的名称改为 addWithFKButton,并将其“内容”**属性改为 Add (FK)

  12. 从**“工具箱”中,将一个“Button”控件拖到“MainWindow”设计图面上。 将“Button”控件的名称改为 addWithNavPropButton,并将其“内容”**属性改为 Add (Nav Prop)

现在,就完成了用户界面。

使用外键属性添加相关实体

在此过程中,您将向应用程序中添加允许使用外键属性添加新课程和系的代码。

使用外键属性添加相关实体

  1. 打开 MainWindow.xaml.vbMainWindow.xaml.cs 文件并添加以下 Using (C#) 或 Imports (Visual Basic) 语句:

    Imports System.Data.Objects
    
    using System.Data.Objects;
    
  2. MainWindow 类中添加以下成员。 这是将向其中添加对象的 ObjectContext

    Private context As SchoolEntities
    
    private SchoolEntities context;
    
  3. Window_Loaded 方法中的代码替换为以下代码,该代码在 GridView 控件中填充系:

    context = New SchoolEntities()
    Dim departmentsViewSource As CollectionViewSource = _
        DirectCast((Me.FindResource("DepartmentsViewSource")),  _
            CollectionViewSource)
    Dim departmentsQuery As ObjectQuery(Of Department) = _
        Me.GetDepartmentsQuery(context)
    departmentsViewSource.Source = _
        departmentsQuery.Execute(MergeOption.AppendOnly)
    
    context = new SchoolEntities();
    CollectionViewSource departmentsViewSource =
        ((CollectionViewSource)(this.FindResource("departmentsViewSource")));
    ObjectQuery<Department> departmentsQuery =
          this.GetDepartmentsQuery(context);
    departmentsViewSource.Source =
        departmentsQuery.Execute(MergeOption.AppendOnly);
    
  4. 在**“MainWindow”**设计图面上,双击 New Department 按钮。

    newDepartment_Checked 方法将添加到代码隐藏文件中。

  5. 将以下代码添加到 newDepartment_Checked 方法中。 这将允许您向 ObjectContext 添加新系。

    Dim departmentsViewSource As CollectionViewSource = _
        DirectCast((FindResource("DepartmentsViewSource")),  _
            CollectionViewSource)
    If newDepartment.IsChecked = True Then
        departmentsViewSource.Source = Nothing
        DepartmentIDTextBox.IsEnabled = True
        BudgetTextBox.IsEnabled = True
        StartDateDatePicker.IsEnabled = True
        AdministratorTextBox.IsEnabled = True
    End If
    
    CollectionViewSource departmentsViewSource =
        (CollectionViewSource)(FindResource("departmentsViewSource"));
    if (newDepartment.IsChecked == true)
    {
        departmentsViewSource.Source = null;
        departmentIDTextBox.IsEnabled = true;
        budgetTextBox.IsEnabled = true;
        startDateDatePicker.IsEnabled = true;
        administratorTextBox.IsEnabled = true;
    }
    
  6. 在**“MainWindow”**设计图面上,双击 Add (FK) 按钮。

    addWithFKButton_Click 方法将添加到代码隐藏文件中。

  7. 将以下代码添加到 addWithFKButton_Click 方法中。 请注意,通过设置新课程的 DepartmentID 属性,可将新课程与系关联。

    If newDepartment.IsChecked = True Then
        Dim dept As New Department()
        dept.DepartmentID = Convert.ToInt32(DepartmentIDTextBox.Text)
        dept.Name = NameComboBox.Text
        dept.Budget = Convert.ToInt32(BudgetTextBox.Text)
        dept.StartDate = Convert.ToDateTime(StartDateDatePicker.SelectedDate)
        dept.Administrator = Convert.ToInt32(AdministratorTextBox.Text)
        context.Departments.AddObject(dept)
    End If
    
    Dim course As New Course()
    course.CourseID = Convert.ToInt32(CourseIDTextBox.Text)
    course.Title = TitleTextBox.Text
    course.Credits = Convert.ToInt32(CreditsTextBox.Text)
    ' The new course is associated with a department
    ' by setting the DepartmentID property.
    course.DepartmentID = Convert.ToInt32(DepartmentIDTextBox.Text)
    context.Courses.AddObject(course)
    context.SaveChanges()
    
    if (newDepartment.IsChecked == true)
    {
        Department dept = new Department
        {
            DepartmentID = Convert.ToInt32(departmentIDTextBox.Text),
            Name = nameComboBox.Text,
            Budget = Convert.ToInt32(budgetTextBox.Text),
            StartDate = Convert
                      .ToDateTime(startDateDatePicker.SelectedDate),
            Administrator = Convert
                      .ToInt32(administratorTextBox.Text)
        };
        context.Departments.AddObject(dept);
    }
    Course course = new Course
    {
        CourseID = Convert.ToInt32(courseIDTextBox.Text),
        Title = titleTextBox.Text,
        Credits = Convert.ToInt32(creditsTextBox.Text),
        // The new course is associated with a department
        // by setting the DepartmentID property.
        DepartmentID = Convert.ToInt32(departmentIDTextBox.Text)
    };
    context.Courses.AddObject(course);
    context.SaveChanges();
    
Ee828425.note(zh-cn,VS.100).gif注意:
如果您同时添加了新课程和新系,则在调用 SaveChanges 之前,不会同步它们的导航属性。例如,如果在调用 SaveChanges 之前尝试通过新课程上的导航属性访问新系,则会返回 null

Crtl+F5 运行该程序。 可以通过编辑课程信息并单击 Add (FK) 来向所选系添加新课程。 可以通过选中 New Department 复选框,编辑课程和系信息,然后单击 Add (FK) 来向新系添加新课程。

使用导航属性添加相关实体

在此过程中,您将向应用程序中添加允许使用导航属性添加新课程和系的代码。

过程标题

  1. 在**“MainWindow”**设计图面上,双击 Add (Nav Prop) 按钮。

    addWithNavPropButton_Click 方法将添加到代码隐藏文件中。

  2. 将以下代码添加到 addWithNavPropButton_Click 方法中。 请注意,通过设置新课程的 Department 导航属性,可将新课程与系关联。 这样还会将新课程添加到 ObjectContext 中。

    Dim dept As Department
    If newDepartment.IsChecked = True Then
        dept = New Department()
        dept.DepartmentID = Convert.ToInt32(DepartmentIDTextBox.Text)
        dept.Name = NameComboBox.Text
        dept.Budget = Convert.ToInt32(BudgetTextBox.Text)
        dept.StartDate = Convert.ToDateTime(StartDateDatePicker.SelectedDate)
        dept.Administrator = Convert.ToInt32(AdministratorTextBox.Text)
        context.Departments.AddObject(dept)
    Else
        dept = DirectCast(NameComboBox.SelectedItem, Department)
    End If
    
    Dim course As New Course()
    course.CourseID = Convert.ToInt32(CourseIDTextBox.Text)
    course.Title = TitleTextBox.Text
    course.Credits = Convert.ToInt32(CreditsTextBox.Text)
    ' The new course is associated with a department
    ' by setting the Department navigation property.
    ' This also adds the new course to the context.
    course.Department = dept
    context.Courses.AddObject(course)
    context.SaveChanges()
    
    Department dept;
    if (newDepartment.IsChecked == true)
    {
        dept = new Department
        {
            DepartmentID = Convert.ToInt32(departmentIDTextBox.Text),
            Name = nameComboBox.Text,
            Budget = Convert.ToInt32(budgetTextBox.Text),
            StartDate = Convert
                        .ToDateTime(startDateDatePicker.SelectedDate),
            Administrator = Convert.ToInt32(administratorTextBox.Text)
        };
        context.Departments.AddObject(dept);
    }
    else
    {
        dept = (Department)nameComboBox.SelectedItem;
    }
    
    Course course = new Course
    {
        CourseID = Convert.ToInt32(courseIDTextBox.Text),
        Title = titleTextBox.Text,
        Credits = Convert.ToInt32(creditsTextBox.Text),
        // The new course is associated with a department
        // by setting the Department navigation property.
        // This also adds the new course to the context.
        Department = dept
    };
    context.SaveChanges();
    

Crtl+F5 运行该程序。 可以通过编辑课程信息并单击 Add (Nav Prop) 来向所选系添加新课程。 可以通过选中“New Department”复选框,编辑课程和系信息,然后单击 Add (Nav Prop) 来向新系添加新课程。

另请参见

任务

如何:创建新的 .edmx 文件(实体数据模型工具)

其他资源

Working with Foreign Keys (Entity Framework)