本演练演示如何使用 Entity Framework Designer(EF Designer)修改模型,将多个实体类型映射到单个表。
你可能会想使用表拆分的一个原因是,通过延迟加载来加载对象时,可以推迟某些属性的加载。 可以将可能包含大量数据的属性分隔到单独的实体中,并且仅在需要时加载它。
下图显示了使用 EF 设计器时使用的主窗口。
先决条件
若要完成本演练,需要:
- Visual Studio 的最新版本。
- 学校示例数据库。
设置项目
本演练使用 Visual Studio 2012。
- 打开 Visual Studio 2012。
- 在 “文件” 菜单上,指向 “新建” ,然后单击 “项目” 。
- 在左窗格中,单击“Visual C#”,然后选择控制台应用程序模板。
- 输入 TableSplittingSample 作为项目的名称,然后单击“ 确定”。
基于学校数据库创建模型
- 右键单击解决方案资源管理器中的项目名称,指向 “添加”,然后单击“ 新建项”。
- 从左侧菜单中选择 “数据” ,然后在“模板”窗格中选择 ADO.NET 实体数据模型 。
- 为文件名输入 TableSplittingModel.edmx ,然后单击“ 添加”。
- 在“选择模型内容”对话框中,选择“ 从数据库生成”,然后单击“ 下一步”。
- 单击“新建连接”。 在“连接属性”对话框中,输入服务器名称(例如 (localdb)\mssqllocaldb),选择身份验证方法,键入 School 以获取数据库名称,然后单击“ 确定”。 “选择数据连接”对话框使用数据库连接设置进行更新。
- 在“选择数据库对象”对话框中,展开 “表” 节点并检查 Person 表。 这会将指定的表添加到 学校 模型。
- 单击“完成”。
将显示实体设计器,该设计器提供用于编辑模型的设计图面。 在“ 选择数据库对象 ”对话框中选择的所有对象都会添加到模型中。
将两个实体映射到单个表
在本部分中,你将Person实体拆分为两个实体,然后将其映射到单个表。
注释
Person 实体不包含可能包含大量数据的任何属性;它只是用作示例。
- 右键单击设计图面的空白区域,指向“ 添加新”,然后单击“ 实体”。 此时会显示“ 新建实体 ”对话框。
- 为HireInfo类型的实体名称和PersonID类型的Key 属性名称键入。
- 单击 “确定” 。
- 新实体类型在设计图面上创建并显示。
- 选择 Person 实体类型的 HireDate 属性,然后按 Ctrl+X 键。
- 选择 HireInfo 实体,然后按 Ctrl+V 键。
- 创建 Person 和 HireInfo 之间的关联。 为此,请右键单击设计图面的空白区域,指向“ 添加新”,然后单击“ 关联”。
- 此时会显示“ 添加关联 ”对话框。 默认情况下会提供 PersonHireInfo 名称。
- 在关系的两端指定乘数 1(一)。
- 按下“确定”。
下一步需要 “映射详细信息” 窗口。 如果看不到此窗口,请右键单击设计图面,然后选择“ 映射详细信息”。
选择 HireInfo 实体类型,然后在 映射详细信息 窗口中单击 <添加表或视图>。
从<“添加表或视图”>字段下拉列表中选择人员。 该列表包含所选实体可映射到的表或视图。 默认情况下,应映射相应的属性。
在设计界面上选择 PersonHireInfo 关联。
右键单击设计图面上的关联并选择“ 属性”。
在 “属性” 窗口中,选择 “引用约束 ”属性,然后单击省略号按钮。
从“主体”下拉列表中选择“人员”。
按下“确定”。
使用模型
- 将以下代码粘贴到 Main 方法中。
using (var context = new SchoolEntities())
{
Person person = new Person()
{
FirstName = "Kimberly",
LastName = "Morgan",
Discriminator = "Instructor",
};
person.HireInfo = new HireInfo()
{
HireDate = DateTime.Now
};
// Add the new person to the context.
context.People.Add(person);
// Insert a row into the Person table.
context.SaveChanges();
// Execute a query against the Person table.
// The query returns columns that map to the Person entity.
var existingPerson = context.People.FirstOrDefault();
// Execute a query against the Person table.
// The query returns columns that map to the Instructor entity.
var hireInfo = existingPerson.HireInfo;
Console.WriteLine("{0} was hired on {1}",
existingPerson.LastName, hireInfo.HireDate);
}
- 编译并运行应用程序。
由于运行此应用程序,以下 T-SQL 语句针对 School 数据库执行。
执行 `context.SaveChanges()` 后,以下 INSERT 被执行,并合并了 Person 和 HireInfo 实体中的数据。
执行 context.People.FirstOrDefault() 后,执行了下面的 SELECT,仅选择映射到 Person 的列。
由于访问 existingPerson.Instructor 的导航属性,执行了以下 SELECT,仅选择映射到 HireInfo 的列