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系列教程汇总

Entity Framework入门教程(14)---DbFirst下的存储过程的更多相关文章

  1. Entity Framework入门教程(1)---Entity Framework简介

    什么是Entity Framework 学习EF的前提:熟练使用Linq和Ado.net,因为在使用EF框架进行开发时,我们大多数情况使用Linq进行查询和操作,而EF的底层实现用的是Ado.net. ...

  2. Entity Framework入门教程(3)---EF中的上下文简介

    1.DbContext(上下文类) 在DbFirst模式中,我们添加一个EDM(Entity Data Model)后会自动生成一个.edmx文件,这个文件中包含一个继承DbContext类的上下文实 ...

  3. Entity Framework入门教程(16)---Enum

    EF DbFirst模式中的枚举类型使用 这一节介绍EF DbFirst模式中的Enum(枚举类型),CodeFirst模式中的Enum会在以后的EF CoreFirst系列中介绍.EF5中添加了对E ...

  4. ASP .NET MVC 之Entity Framework入门教程及源码

    本文主要的目的是 1. 说明Entity Framework Power Tools如何使用. 2. Entity Framework  快速门 实验环境: OS: Windows Server 20 ...

  5. Entity Framework入门教程:创建实体数据模型

    下图为一个已经创建好的数据库表关系 实体数据模型的创建过程 在Visual Studio项目中,右键程序集菜单,选择[添加]->[新建项],在[添加新项窗口]中选择[ADO.NET实体数据模型] ...

  6. Entity Framework入门教程:什么是Entity Framework

    Entity Framework简介 Entity Framework是微软提供的一个O/RM(对象关系映射)框架.它基于ADO.NET,为开发人员提供了一种自动化的机制来访问和存储数据库中的数据. ...

  7. Entity Framework入门教程(8)---预先加载、延迟加载、显示加载

    1.预先加载 预先加载:在对一种类型的实体进行查询时,将相关的实体作为查询的一部分一起加载.预先加载可以使用Include()方法实现. 1.加载一个相关实体类型 栗子:使用Include()方法从数 ...

  8. Entity Framework入门教程(9)---离线场景附加实体图集到上下文

    附加离线实体图集到上下文 这节主要内容是通过不同的方法将离线实体附加到上下文中. 在离线场景中,保存一个实体要略微困难一些.当我们保存一个离线的实体图集或一个单独的离线实体时,我们需要做两件事.首先, ...

  9. Entity Framework入门教程(13)---EF中的高并发

    EF中的高并发 这里只介绍EF6中database-first开发方案的高并发解决方案,code-first开发方案中的高并发会在以后的EF CodeFirst系列中介绍. EF默认支持乐观并发:我们 ...

随机推荐

  1. SSH远程登录原理

    使用ssh主要有两种登录方式:第一种为密码口令登录,第二种为公钥登录 密码口令登录 通过密码进行登录,主要流程为: 1.客户端连接上服务器之后,服务器把自己的公钥传给客户端 2.客户端输入服务器密码通 ...

  2. LeetCode算法题-Search in a Binary Search Tree(Java实现)

    这是悦乐书的第295次更新,第314篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第163题(顺位题号是700).给定一个二叉搜索树(BST)的和正整数val. 你需要在 ...

  3. 我的第一个python web开发框架(34)——后台管理系统权限设计

    框架底层和接口终于改造完成了,小白再次找到老菜. 小白:老大,上次你对后台权限系统简单的讲了一下,我一点头绪都没有,现在有空完整的说一说吗? 老菜:说到权限系统,要讲明白真不容易,权限系统并不是越复杂 ...

  4. python3 今日大纲 day05

    1. 上周内容回顾 1. 闭包: 内层函数对外层函数变量的使用 def outer(): a = 10 def inner(): print(a) return inner ret = outer() ...

  5. openstack第四章:neutron— 网络服务

    第四篇neutron— 网络服务 一.neutron 介绍:   Neutron 概述 传统的网络管理方式很大程度上依赖于管理员手工配置和维护各种网络硬件设备:而云环境下的网络已经变得非常复杂,特别是 ...

  6. python线程join方法

    转载:http://www.cnblogs.com/cnkai/p/7504980.html Python多线程与多进程中join()方法的效果是相同的. 下面仅以多线程为例: 首先需要明确几个概念: ...

  7. mpvue-Vant Weapp踩坑记

    微信开发者工具:开发.调试和模拟运行微信小程序的最核心的工具了,所以必须安装 # 全局安装 vue-cli $ npm install --global vue-cli # 创建一个基于 mpvue- ...

  8. 用Python开发小学二年级口算自动出题程序

    版权声明:本文为博主原创文章,欢迎转载,并请注明出处.联系方式:460356155@qq.com 武汉光谷一小二年级要求家长每天要给小孩出口算题目,让孩子练习. 根据老师出题要求编写了Python程序 ...

  9. 在一台计算机上运行两个或多个tomcat

    有的时候我们需要在一台计算计算机上安装多个Tomcat,那我们该怎样配置呢?  ## 1.配置思路: 在操作之前我们先启动一个Tomcat,看一下启动数据: 这里面有我们在环境变量中配置的CATALI ...

  10. sql sever基本命令

    创建表: create table stu_info( id ,) not null primary key clustered, name ) not null, score numeric not ...