定义查询 EF 设计器Defining Query - EF Designer

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

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

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

本主题演示如何执行以下任务。

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

先决条件Prerequisites

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

设置项目Set up the Project

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

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

基于 School 数据库创建模型Create a Model based on the School Database

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

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

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

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

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

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

  • 单击 “ 完成“。

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

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

    XML 编辑器

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

    警告2

添加定义查询Add a Defining Query

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

  • EntitySet 元素添加到 .edmx 文件的 SSDL 部分(第5行到第13行)。 指定下列信息:
    • 仅指定 EntitySet 元素的 名称EntityType 特性。
    • 实体类型的完全限定名称在 EntityType 特性中使用。
    • 要执行的 SQL 语句是在 DefiningQuery 元素中指定的。
  1. <!-- SSDL content -->
  2. <edmx:StorageModels>
  3. <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">
  4. <EntityContainer Name="SchoolModelStoreContainer">
  5. <EntitySet Name="GradeReport" EntityType="SchoolModel.Store.GradeReport">
  6. <DefiningQuery>
  7. SELECT CourseID, Grade, FirstName, LastName
  8. FROM StudentGrade
  9. JOIN
  10. (SELECT * FROM Person WHERE EnrollmentDate IS NOT NULL) AS p
  11. ON StudentID = p.PersonID
  12. </DefiningQuery>
  13. </EntitySet>
  14. <EntitySet Name="Course" EntityType="SchoolModel.Store.Course" store:Type="Tables" Schema="dbo" />
  • EntityType元素添加到 .EDMX 的 SSDL 部分。 文件,如下所示。 注意以下各项:
    • Name特性的值对应于上面的EntitySet元素中的EntityType特性的值,但该实体类型的完全限定名称在EntityType特性中使用。
    • 属性名称对应于DefiningQuery元素(如上所示)中的 SQL 语句返回的列名称。
    • 在此示例中,实体键由三个属性组成以确保唯一键值。
  1. <EntityType Name="GradeReport">
  2. <Key>
  3. <PropertyRef Name="CourseID" />
  4. <PropertyRef Name="FirstName" />
  5. <PropertyRef Name="LastName" />
  6. </Key>
  7. <Property Name="CourseID"
  8. Type="int"
  9. Nullable="false" />
  10. <Property Name="Grade"
  11. Type="decimal"
  12. Precision="3"
  13. Scale="2" />
  14. <Property Name="FirstName"
  15. Type="nvarchar"
  16. Nullable="false"
  17. MaxLength="50" />
  18. <Property Name="LastName"
  19. Type="nvarchar"
  20. Nullable="false"
  21. MaxLength="50" />
  22. </EntityType>

备注

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

向模型添加实体类型Add an Entity Type to the Model

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

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

在 EF 设计器中打开模型。

  • 双击 “DefiningQueryModel”。

  • 对以下消息说为 “是”

    警告2

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

  • 右键单击设计器图面,然后选择 “添加新->”实体 … “。
  • 为 “键” 属性的 “实体名称” 和 “ CourseID “ 指定GradeReport
  • 右键单击 “ GradeReport “ 实体,然后选择 “添加新->”标量属性“。
  • 将属性的默认名称更改为FirstName
  • 添加另一个标量属性,并为名称指定LastName
  • 添加另一个标量属性,并为该名称指定等级
  • 在 “属性“ 窗口中,将评分的 “类型“ 属性更改为Decimal
  • 选择FirstNameLastName属性。
  • 在 “属性“ 窗口中,将EntityKey属性值更改为True

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

  1. <EntitySet Name="GradeReport" EntityType="SchoolModel.GradeReport" />
  2. <EntityType Name="GradeReport">
  3. . . .
  4. </EntityType>

将定义查询映射到实体类型Map the Defining Query to the Entity Type

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

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

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

  1. <EntitySetMapping Name="GradeReports">
  2. <EntityTypeMapping TypeName="IsTypeOf(SchoolModel.GradeReport)">
  3. <MappingFragment StoreEntitySet="GradeReport">
  4. <ScalarProperty Name="LastName" ColumnName="LastName" />
  5. <ScalarProperty Name="FirstName" ColumnName="FirstName" />
  6. <ScalarProperty Name="Grade" ColumnName="Grade" />
  7. <ScalarProperty Name="CourseID" ColumnName="CourseID" />
  8. </MappingFragment>
  9. </EntityTypeMapping>
  10. </EntitySetMapping>
  • 编译应用程序。

在代码中调用定义查询Call the Defining Query in your Code

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

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