EF6中DbFirst模式下使用存储过程

  我们已经知道EF可以将L2E或Entity SQL的查询语句自动转换成SQL命令,也可以根据实体的状态自动生成Insert/update/delete的Sql命令。这节介绍EF中使用预先定义的存储过程对一张或者多种表进行CURD操作。

  EF API会新建一个function来映射数据库中的自定义函数或存储过程。下边讲解EF DbFirst模式下存储过程的用法,EF CodeFirst存储过程的用法会在以后的EF CodeFirst系列中介绍。

1.DbFirst模式——使用存储过程查询数据

第一步 在数据库新建存储过程

首先在数据库创建一个名为GetCoursesByStudentId的存储过程,这个存储过程返回一个学生的所有课程。

CREATE PROCEDURE [dbo].[GetCoursesByStudentId]
-- Add the parameters for the stored procedure here
@StudentId int = null
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON; -- Insert statements for procedure here
select c.courseid, c.coursename,c.Location, c.TeacherId
from student s
left outer join studentcourse sc on sc.studentid = s.studentid
left outer join course c on c.courseid = sc.courseid
where s.studentid = @StudentId
END

第二步 生成EMD

  这一步和普通生成EMD过程是一样的,值得注意的是在Choose Your Database Objects and Settings这一步勾选我们新建的存储过程(GetCoursesByStudentId)和下边的Import selected stored procedures and functions into the entity model ,如下图所示

GetCoursesByStudentId()返回Course实体集合,所以我们不需要返回一个新的复杂类型。右键Function Imports下的GetCoursesByStudentId方法,选择Edit,出现以下界面,把Entities设置为Course即可

通过上边两步,在context中会生成一个GetCoursesByStudentId方法:

现在我们就可以愉快地使用context.GetCoursesByStudentId来执行存储过程了!如下:

using (var context = new SchoolDBEntities())
{
var courses = context.GetCoursesByStudentId(); foreach (Course cs in courses)
Console.WriteLine(cs.CourseName);
}

在数据库中执行的命令为: exec [dbo].[GetCoursesByStudentId] @StudentId=1

一点补充:EF中的表值函数和查询的存储过程使用的步骤是一模一样的(表值函数和存储过程本来就很类似,一个最重要的区别是EF中表值函数的返回值可用linq查询过滤)

2.DbFirst模式——使用存储过程执行CUD操作

这一部分介绍怎么通过存储过程来执行CUD(creat,update,delete)操作。

我们在数据库添加以下几个存储:

Sp_InsertStudentInfo(添加):

CREATE PROCEDURE [dbo].[sp_InsertStudentInfo]
-- Add the parameters for the stored procedure here
@StandardId int = null,
@StudentName varchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON; INSERT INTO [SchoolDB].[dbo].[Student]([StudentName],[StandardId])
VALUES(@StudentName, @StandardId) SELECT SCOPE_IDENTITY() AS StudentId END

sp_UpdateStudent(修改):

CREATE PROCEDURE [dbo].[sp_UpdateStudent]
-- Add the parameters for the stored procedure here
@StudentId int,
@StandardId int = null,
@StudentName varchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON; Update [SchoolDB].[dbo].[Student]
set StudentName = @StudentName,StandardId = @StandardId
where StudentID = @StudentId; END

sp_DeleteStudent(删除):

CREATE PROCEDURE [dbo].[sp_DeleteStudent]
-- Add the parameters for the stored procedure here
@StudentId int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON; DELETE FROM [dbo].[Student]
where StudentID = @StudentId END

第一步:升级EDM

首先我们要升级EDM把这些存储过程添加当我们的EDM中。右键设计器,选择Update Model from Database,就出现了升级界面,如下图所示,展开Stored Procedure and Functions,勾选我们上边创建的三个存储过程,然后点击Finish。

这时模型浏览器中在Store Model中有了这三个存储过程,但是Function Imports中没有,如下所示:

打开模型设计器在Student实体上右键,选择Stored Procedure Mapping,来打开映射详情界面,如下图

在下面的映射详细界面,我们看到<Select Insert Function>, <Select Update Function>, and <Select Delete Function>,给这些下拉菜单分别选择对应的存储过程,同时选择存储过程的输入输出参数,如下图所示:

右击Student实体,选择Validate,确保没有错误

现在我们执行add,update,或者delete时,EF不再执行自动生成的SQL命令,而是通过这些存储过程来执行,下面是一个栗子:

using (var context = new SchoolDBEntities())
{
Student student = new Student() { StudentName = "New student using SP"}; context.Students.Add(student);
//执行 sp_InsertStudentInfo
context.SaveChanges(); student.StudentName = "Edit student using SP";
//执行 sp_UpdateStudent
context.SaveChanges(); context.Students.Remove(student);
//执行 sp_DeleteStudentInfo
context.SaveChanges();
}

调用SaveChange()方法时,在数据库中执行的命令如下:

exec [dbo].[sp_InsertStudentInfo] @StandardId=NULL,@StudentName='New student using SP'
go exec [dbo].[sp_UpdateStudent] @StudentId=47,@StandardId=NULL,@StudentName='Edit student using SP'
go exec [dbo].[sp_DeleteStudent] @StudentId=47
go

注意:无论是使用存储过程还是默认生成的Sql命令,当插入一条记录并执行完SaveChange()方法后,这个新的实例会立即分配一个Id。这样设计是为了有效地追踪实体,让我们可以对实体执行进一步的操作(如没有id执行update会抛出异常),如下图:

EF系列目录链接:Entity Franmework系列教程汇总

最新文章

  1. 9.30notes
  2. 30 GroupSock(Port)——live555源码阅读(四)网络
  3. Intellij IDEA中配置Maven
  4. Charles 应用
  5. ubuntu 14.04 apt-get 方式安装oracle JDK
  6. hdu1690 Bus System (dijkstra)
  7. K:HashMap中hash函数的作用
  8. 【工具】-RAP接口管理工具
  9. vue传参二
  10. hibernate状态转换关系图【原】
  11. spring quartz整合实现定时器自动注解
  12. Visual Studio 2013 sqlce 配置(转)
  13. 【leetcode 简单】 第六十三题 使用队列实现栈
  14. Android Studio 升级为3.1 踩到的坑
  15. otl中遇到的一些字符数组长度问题
  16. iOS开发者有价值的工具集
  17. linux中校验文件完整性(md5,sha1)
  18. map按值排序
  19. springBoot service层 事务控制
  20. Java中Collections和Collection的区别

热门文章

  1. Saltstack_使用指南05_数据系统-Pillar
  2. Django REST framework基础:版本控制
  3. Redhat7.3更换CentOS7 yum源
  4. day21-多并发编程基础(二)
  5. zabbix优化,配合文件,zabbix_get命令
  6. (十四)Exploring Your Data
  7. 一文搞懂Raft算法
  8. 实现简单的printf函数
  9. C# 递归构造树状数据结构(泛型),如何构造?如何查询?
  10. Java实现动态修改Jar包内文件内容