定义查询 - EF Designer
本演练演示如何使用 EF Designer 向模型添加定义查询和相应的实体类型。 定义查询通常用于提供类似于数据库视图(但该视图是在模型中定义的,而不是在数据库中定义)所提供的功能。 使用定义查询可执行在 .edmx 文件的 DefiningQuery 元素中指定的 SQL 语句。 有关详细信息,请参阅 SSDL 规范中的 DefiningQuery。
使用定义查询时,还必须在模型中定义实体类型。 实体类型用于显示由定义查询公开的数据。 请注意,通过此实体类型显示的数据是只读的。
无法将参数化查询作为定义查询执行。 但是,可以通过将显示数据的实体类型的插入、更新和删除函数映射到存储过程来更新数据。 有关详细信息,请参阅使用存储过程插入、更新和删除。
本主题说明如何执行以下任务。
- 添加定义查询
- 将实体类型添加到模型
- 将定义查询映射到实体类型
先决条件
若要完成此演练,您需要:
- Visual Studio 的最新版本。
- School 示例数据库。
设置项目
本演练使用 Visual Studio 2012 或更高版本。
- 打开 Visual Studio。
- 在 “文件” 菜单上,指向 “新建” ,然后单击 “项目” 。
- 在左侧窗格中,单击“Visual C#”,然后选择“控制台应用程序”模板。
- 输入 DefiningQuerySample 作为项目名称,然后单击“确定”。
创建基于 School 数据库的模型
在“解决方案资源管理器”中右键单击该项目的名称,指向“添加”,然后单击“新建项”。
从左侧菜单中选择“数据”,然后在“模板”窗格中选择“ADO.NET 实体数据模型”。
输入“DefiningQueryModel.edmx”作为文件名,然后单击“添加”。
在“选择模型内容”对话框中,选择“从数据库生成”,然后单击“下一步”。
单击“新建连接”。 在“连接属性”对话框中,输入服务器名称(例如 (localdb)\mssqllocaldb),选择身份验证方法,键入 School 作为数据库名称,然后单击“确定”。 “选择数据连接”对话框将根据你的数据库连接设置进行更新。
在“选择数据库对象”对话框中,选中“表”节点。 这会将所有表添加到 School 模型中。
单击“完成” 。
在“解决方案资源管理器”中,右键单击 DefiningQueryModel.edmx 文件并选择“打开方式...”。
选择“XML (文本)编辑器”。
如果出现以下消息提示,请单击“是”:
添加定义查询
在此步骤中,我们将使用 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。
对于以下消息提示,请单击“是”:
将显示 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 实体类型之间的默认映射。
因此,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);
}