定义查询 - EF Designer

本演练演示如何使用 EF Designer 向模型添加定义查询和相应的实体类型。 定义查询通常用于提供类似于数据库视图(但该视图是在模型中定义的,而不是在数据库中定义)所提供的功能。 使用定义查询可执行在 .edmx 文件的 DefiningQuery 元素中指定的 SQL 语句。 有关详细信息,请参阅 SSDL 规范中的 DefiningQuery

使用定义查询时,还必须在模型中定义实体类型。 实体类型用于显示由定义查询公开的数据。 请注意,通过此实体类型显示的数据是只读的。

无法将参数化查询作为定义查询执行。 但是,可以通过将显示数据的实体类型的插入、更新和删除函数映射到存储过程来更新数据。 有关详细信息,请参阅使用存储过程插入、更新和删除

本主题说明如何执行以下任务。

  • 添加定义查询
  • 将实体类型添加到模型
  • 将定义查询映射到实体类型

先决条件

若要完成此演练,您需要:

设置项目

本演练使用 Visual Studio 2012 或更高版本。

  • 打开 Visual Studio。
  • “文件” 菜单上,指向 “新建” ,然后单击 “项目”
  • 在左侧窗格中,单击“Visual C#”,然后选择“控制台应用程序”模板
  • 输入 DefiningQuerySample 作为项目名称,然后单击“确定”

 

创建基于 School 数据库的模型

  • 在“解决方案资源管理器”中右键单击该项目的名称,指向“添加”,然后单击“新建项”

  • 从左侧菜单中选择“数据”,然后在“模板”窗格中选择“ADO.NET 实体数据模型”

  • 输入“DefiningQueryModel.edmx”作为文件名,然后单击“添加”

  • 在“选择模型内容”对话框中,选择“从数据库生成”,然后单击“下一步”

  • 单击“新建连接”。 在“连接属性”对话框中,输入服务器名称(例如 (localdb)\mssqllocaldb),选择身份验证方法,键入 School 作为数据库名称,然后单击“确定”。 “选择数据连接”对话框将根据你的数据库连接设置进行更新。

  • 在“选择数据库对象”对话框中,选中“表”节点。 这会将所有表添加到 School 模型中

  • 单击“完成” 。

  • 在“解决方案资源管理器”中,右键单击 DefiningQueryModel.edmx 文件并选择“打开方式...”

  • 选择“XML (文本)编辑器”

    XML Editor

  • 如果出现以下消息提示,请单击“是”

    Warning 2

 

添加定义查询

在此步骤中,我们将使用 XML 编辑器将定义查询和实体类型添加到 .edmx 文件的 SSDL 部分。 

  • 将 EntitySet 元素添加到 .edmx 文件的 SSDL 部分(第 5 行到第 13 行)。 指定以下内容:
    • 仅指定 EntitySet 元素的 Name 和 EntityType 属性
    • 在 EntityType 属性中使用了实体类型的完全限定名
    • 在 DefiningQuery 元素中指定要执行的 SQL 语句
    <!-- SSDL content -->
    <edmx:StorageModels>
      <Schema Namespace="SchoolModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/11/edm/ssdl">
        <EntityContainer Name="SchoolModelStoreContainer">
           <EntitySet Name="GradeReport" EntityType="SchoolModel.Store.GradeReport">
              <DefiningQuery>
                SELECT CourseID, Grade, FirstName, LastName
                FROM StudentGrade
                JOIN
                (SELECT * FROM Person WHERE EnrollmentDate IS NOT NULL) AS p
                ON StudentID = p.PersonID
              </DefiningQuery>
          </EntitySet>
          <EntitySet Name="Course" EntityType="SchoolModel.Store.Course" store:Type="Tables" Schema="dbo" />
  • 将 EntityType 元素添加到 .edmx 文件的 SSDL 部分, 如下所示。 注意以下事项:
    • Name 属性的值对应于上述 EntitySet 元素中的 EntityType 属性的值,尽管在 EntityType 属性中使用了实体类型的完全限定名称
    • 属性名称对应于上述 DefiningQuery 元素中的 SQL 语句返回的列名称
    • 在此示例中,实体键由三个属性组成以确保唯一键值。
    <EntityType Name="GradeReport">
      <Key>
        <PropertyRef Name="CourseID" />
        <PropertyRef Name="FirstName" />
        <PropertyRef Name="LastName" />
      </Key>
      <Property Name="CourseID"
                Type="int"
                Nullable="false" />
      <Property Name="Grade"
                Type="decimal"
                Precision="3"
                Scale="2" />
      <Property Name="FirstName"
                Type="nvarchar"
                Nullable="false"
                MaxLength="50" />
      <Property Name="LastName"
                Type="nvarchar"
                Nullable="false"
                MaxLength="50" />
    </EntityType>

注意

如果稍后运行“更新模型向导”对话框,则对存储模型所做的任何更改(包括定义查询)都将被覆盖

 

将实体类型添加到模型

在此步骤中,我们将使用 EF Designer 将实体类型添加到概念模型。  注意以下事项:

  • 实体的 Name 对应于上述 EntitySet 元素中 EntityType 属性的值
  • 属性名称对应于上述 DefiningQuery 元素中的 SQL 语句返回的列名称
  • 在此示例中,实体键由三个属性组成以确保唯一键值。

在 EF Designer 中打开模型。

  • 双击 DefiningQueryModel.edmx。

  • 对于以下消息提示,请单击“是”

    Warning 2

 

将显示 Entity Designer,它提供用于编辑模型的设计图面。

  • 右键单击设计图面并选择“添加新项”->“实体...”
  • 指定 GradeReport 作为为实体名称,指定 CourseID 作为“键属性”
  • 右键单击 GradeReport 实体并选择“添加新实体”->“标量属性”
  • 将属性的默认名称更改为 FirstName
  • 添加另一个标量属性,并指定 LastName 作为名称
  • 添加另一个标量属性,并指定 Grade 作为名称
  • 在“属性”窗口中,将 Grade 的 Type 属性更改为 Decimal
  • 选择 FirstName 和 LastName 属性
  • 在“属性”窗口中,将 EntityKey 属性值更改为 True

因此,以下元素被添加到 .edmx 文件的 CSDL 部分

    <EntitySet Name="GradeReport" EntityType="SchoolModel.GradeReport" />

    <EntityType Name="GradeReport">
    . . .
    </EntityType>

 

将定义查询映射到实体类型

在此步骤中,我们将使用“映射详细信息”窗口映射概念和存储实体类型。

  • 右键单击设计图面上的 GradeReport 实体并选择“表映射”
    将出现“映射详细信息”窗口
  • 从“<添加表或视图>”下拉列表(位于“表”下)中选择 GradeReport
    将显示概念和存储 GradeReport 实体类型之间的默认映射
    Mapping Details3

因此,EntitySetMapping 元素将添加到 .edmx 文件的映射部分。 

    <EntitySetMapping Name="GradeReports">
      <EntityTypeMapping TypeName="IsTypeOf(SchoolModel.GradeReport)">
        <MappingFragment StoreEntitySet="GradeReport">
          <ScalarProperty Name="LastName" ColumnName="LastName" />
          <ScalarProperty Name="FirstName" ColumnName="FirstName" />
          <ScalarProperty Name="Grade" ColumnName="Grade" />
          <ScalarProperty Name="CourseID" ColumnName="CourseID" />
        </MappingFragment>
      </EntityTypeMapping>
    </EntitySetMapping>
  • 编译该应用程序。

 

在代码中调用定义查询

现在,可使用 GradeReport 实体类型执行定义查询。 

    using (var context = new SchoolEntities())
    {
        var report = context.GradeReports.FirstOrDefault();
        Console.WriteLine("{0} {1} got {2}",
            report.FirstName, report.LastName, report.Grade);
    }