Entity Framework 6 Recipes 2nd Edition(10-7)译 -> TPH继承模型中使用存储过程

时间:2021-12-13 06:20:20

10-7. TPH继承模型中使用存储过程

问题

用一个存储过程来填充TPH继承模型的实体

解决方案

假设已有如Figure 10-7所示模型. 我们有两个派生实体: Instructor(教员)和Student(学生).

这个模型使用TPH继承方式,所以数据库中只有一个表. Person(人员)表有一个鉴别列,用来把表的记录映射到不同的派生实体上. 我们想用一个存储过程来填充实体.

Entity Framework 6 Recipes 2nd Edition(10-7)译 -> TPH继承模型中使用存储过程

Figure 10-7. A model for instructors and students

用下面的步骤,达到用一个存储过程来返回实体的目的:

1.在你的数据库中创建如Listing 10-18所示的存储过程. 这个存储过程返回所有人员.

Listing 10-18. The GetAllPeople Stored Procedure, Which Returns All the People, Both

Students and Instructors, in the Model

create procedure [Chapter10].[GetAllPeople]

as

begin

select * from chapter10.Person

end

2. 右击模型的设计视图,选择“从数据库更新模型”.选择存储过程GetAllPeople. 单击“完成”,把存储过程添加到模型中.

3. ( 译注:我的环境是win10+vs2013+ef6.1.3,是不需要这步的,第1步已经把这步也完成了,只是最后的“返回以下内容的集合”必须修改一下),右击模型的设计视图, 选择“新增“ ➤ 函数导入. 从“存储过程/函数名称”下拉框中选择GetAllPeople. 在“函数导入名称“文本框中输入:GetAllPeople. 这个就是在模型中的方法名称.在“返回以下内容的集合”里勾选“实体”,在下拉框里选择Person.单击“确定”.将会创建<FunctionImportMapping>框架.

4. 右击 .edmx 文件, 选择“打开方式” ➤ XML Editor.编辑.edmx文件的mapping 小节下

的<FunctionImportMapping> 标签,用 Listing 10-19所示代码去匹配(因为像EF6RecipesModel的命名与你的例子可能不同).它会映射被存储过程返回的列与Person类型的实体的属性。

(译注:所给的示例数据库里的PersonType列,类型为varchar,不可为空。我自己跟着这里所说的步骤做了一下,运行后发现有错误。看了原书网站上下载的代码后发现这一列为nvarchar,并且可为空,所以改了数据库之后,再“从数据库更新模型”一次,就可以了。)

Listing 10-19. The FunctionImportMapping Conditionally Maps Rows to Either the

Instructor or Student Entity

<FunctionImportMapping FunctionImportName="GetAllPeople"

FunctionName="EF6RecipesModel.Store.GetAllPeople">

<ResultMapping>

<EntityTypeMapping TypeName="EFRecipesModel.Student">

<ScalarProperty Name="Degree" ColumnName="Degree" />

<Condition ColumnName="PersonType" Value="Student"/>

</EntityTypeMapping>

<EntityTypeMapping TypeName="EF6RecipesModel.Instructor">

<ScalarProperty Name="Salary" ColumnName="Salary"/>

<Condition ColumnName="PersonType" Value="Instructor"/>

</EntityTypeMapping>

</ResultMapping>

</FunctionImportMapping>

5. Follow the pattern in Listing 10-20 to use the GetAllPeople stored procedure via the

GetAllPeople() method

Listing 10-20. Querying the Model Using the GetAllPeople Stored Procedure via

the GetAllPeople() Method.

static void Main(string[] args)

{

using (var context = new EFRecipesEntities1007())

{

context.People.Add(new Instructor

{

Name = "Karen Stanford",

Salary = 62500M

});

context.People.Add(new Instructor

{

Name = "Robert Morris",

Salary = 61800M

});

context.People.Add(new Student

{

Name = "Jill Mathers",

Degree = "Computer Science"

});

context.People.Add(new Student

{

Name = "Steven Kennedy",

Degree = "Math"

});

context.SaveChanges();

}

using (var context = new EFRecipesEntities1007())

{

Console.WriteLine("Instructors and Students");

var allPeople = context.GetAllPeople();

foreach (var person in allPeople)

{

if (person is Instructor)

Console.WriteLine("Instructor {0} makes {1}/year",

person.Name,

((Instructor)person).Salary);

else if (person is Student)

Console.WriteLine("Student {0}'s major is {1}",

person.Name, ((Student)person).Degree);

}

}

Console.WriteLine("\npress any key to exit...");

Console.ReadKey();

}

输出结果如Listing 10-20:

===================================================================

Instructors and Students

Instructor Karen Stanford makes $62,500.00/year

Instructor Robert Morris makes $61,800.00/year

Student Jill Mathers's major is Computer Science

Student Steven Kennedy's major is Math

=================================================================================

它是如何工作的

用一个存储过程填充TP继承模型的实体,比TPT (见10-6小节)要简单些. 这里的存储过程只是检索出表Person的所有行. 我们在<FunctionImportMapping>标签里对应关系(列名+值来确定是某种实体),(见 Listing 10-19),就是把表的鉴别列(PersonType)的不同的值,转化为相对应的实体

.在10-6小节我们这么做,在本小节,我们也是这么做。

附:创建示例用到的数据库的脚本文件