一. 背景

  上一个章节,介绍了EF调用两类SQL语句,主要是借助 ExecuteSqlCommand  和 SqlQuery 两个方法来完成,在本章节主要是复习几类存储过程的写法和对应的EF调用这几类存储过程的写法,另外介绍EF的DBFirst模式的下EF存储过程的特有写法。

  本章要达到以下几个目标:

  ① 熟练掌握存储过程的相关概念和几类写法(去复习)

  ② EF各种模式调用各种存储过程的通用写法(也是借助  ExecuteSqlCommand  和 SqlQuery )

  ③ EF的DBFirst模式事先映射好存储过程,简洁调用的写法

二. EF调用存储过程

  EF调用存储过程通用的写法,分两类:  

  ① 对于查询相关的存储过程,调用 SqlQuery 方法

  ② 对于增删改或其他的存储过程,调用 ExecuteSqlCommand 方法

1. 不含任何参数(查询类的存储过程)

  直接调用SqlQuery方法进行操作。

 if (exists (select * from sys.objects where name = 'GetAll'))
drop proc GetAll
go
create proc GetAll
as
select * from TestOne; -- 调用
exec GetAll;
       private static void NewMethod(DbContext db)
{
Console.WriteLine("---------------------------------1. 测试查询所有数据(不含输入参数)----------------------------------------");
List<TestOne> tList = db.Database.SqlQuery<TestOne>("GetAll").ToList();
foreach (var item in tList)
{
Console.WriteLine("id为:{0},t1为:{1},t2为:{2}", item.id, item.t1, item.t2);
}
}

2. 含多个输入参数(查询类的存储过程)

  调用SqlQuery方法进行操作,传入参数的使用要使用SqlParameter参数化的方式进行传入,特别注意:调用时,存储过程的名字后面的参数 必须按照SqlParameter中的先后顺序来写

 if (exists (select * from sys.objects where name = 'GetALLBy'))
drop proc GetALLBy
go
create proc GetALLBy(
@id varchar(),
@t1 varchar()
)
as
select * from TestOne where id=@id and t1=@t1; exec GetALLBy @id='',@t1='';
      private static void NewMethod2(DbContext db)
{
Console.WriteLine("---------------------------------2. 测试根据指定条件查询数据(含输入参数)----------------------------------------");
SqlParameter[] para ={
new SqlParameter("@id",""),
new SqlParameter("@t1","txt1")
};
//调用的时,存储过程的名字后面的参数 必须按照SqlParameter中的先后顺序来写
List<TestOne> tList = db.Database.SqlQuery<TestOne>("GetALLBy @id,@t1", para).ToList();
foreach (var item in tList)
{
Console.WriteLine("id为:{0},t1为:{1},t2为:{2}", item.id, item.t1, item.t2);
}
}

3. 增删改的存储过程(含1个输入参数)

  调用 ExecuteSqlCommand  方法来执行,针对输入参数,要采用SqlParameter的方式来进行传参数

 if (exists (select * from sys.objects where name = 'DoSome'))
drop proc DoSome
go
create proc DoSome(
@id varchar()
)
as
begin transaction
begin try
truncate table [dbo].[TestOne];
insert into TestOne values(@id,'','');
delete from TestOne where id=''
commit transaction
end try
begin catch
rollback transaction
end catch exec DoSome
  private static void NewMethod3(DbContext db)
{
Console.WriteLine("---------------------------------3. 测试根据指定条件查询数据(含输入参数)----------------------------------------");
SqlParameter[] para ={
new SqlParameter("@id",Guid.NewGuid().ToString("N")),
};
int n = db.Database.ExecuteSqlCommand("DoSome @id", para);
if (n > )
{
Console.WriteLine("操作成功");
}
else
{
Console.WriteLine("没有更多数据进行处理");
} }

4. 带输出参数的存储过程的调用

 GO
if (exists (select * from sys.objects where name = 'GetT1Value'))
drop proc GetT1Value
go
create proc GetT1Value(
@t1 varchar(32),
@count int output
)
as
select @count=count(*) from TestOne where t1=@t1;
select * from TestOne where t1=@t1;
go
declare @myCount int;
exec GetT1Value '',@myCount output;
select @myCount as myCount;
    private static void NewMethod4(DbContext db)
{
Console.WriteLine("---------------------------------4. 测试查询含有输入和输出操作----------------------------------------");
//把输出参数单独拿出来声明
SqlParameter para1 = new SqlParameter("@t2", SqlDbType.Int);
para1.Direction = ParameterDirection.Output;
//把输出参数放到数组里
SqlParameter[] para2 ={
new SqlParameter("@t1",""),
para1
};
var tList1 = db.Database.SqlQuery<TestOne>("exec GetT1Value @t1,@t2 out", para2).ToList();
//通过输出参数在数组中的位置来获取返回值。
var count = para2[].Value; Console.WriteLine($"数量count为:{count}");
foreach (var item in tList1)
{
Console.WriteLine("id为:{0},t1为:{1},t2为:{2}", item.id, item.t1, item.t2);
} }

 PS:这种调用方式,需要先声明一下输出类型,然后把输出参数放到SqlParameter这个数组里,执行完后,通过数值下标.Value来获取这个返回值。(和DBFirst模式下调用有所不同)

三. DBFirst模式快捷调用存储过程

  前面介绍的调用存储过程的方法是通用模式,无论EF的哪种模式都可以使用,这里将介绍DBFirst模式的快捷调用,原理即创建的时候将存储过程映射进来了,所以可以直接调用。如下图:

1. 不含任何参数(查询类存储过程)

 -- .无参存储过程(查询)
if (exists (select * from sys.objects where name = 'GetAll'))
drop proc GetAll
go
create proc GetAll
as
select * from DBTestOne; -- 调用
exec GetAll;
    private static void DBNewMethod(EFDB3Entities db)
{
Console.WriteLine("---------------------------------1. 测试查询所有数据(不含输入参数)----------------------------------------");
var tList = db.GetAll().ToList();
foreach (var item in tList)
{
Console.WriteLine("id为:{0},t1为:{1},t2为:{2}", item.id, item.t1, item.t2);
}
}

2. 含多个输入参数(查询类存储过程)

 --. 有参数的存储过程(查询)
if (exists (select * from sys.objects where name = 'GetALLBy'))
drop proc GetALLBy
go
create proc GetALLBy(
@id varchar(),
@t1 varchar()
)
as
select * from DBTestOne where id=@id and t1=@t1; exec GetALLBy @id='',@t1='';
      private static void DBNewMethod2(EFDB3Entities db)
{
Console.WriteLine("---------------------------------2. 测试根据指定条件查询数据(含输入参数)----------------------------------------");
var tList = db.GetALLBy("", "").ToList();
foreach (var item in tList)
{
Console.WriteLine("id为:{0},t1为:{1},t2为:{2}", item.id, item.t1, item.t2);
}
}

3. 增删改存储过程(含1个输入参数)

 --. 增删改的一组过程
if (exists (select * from sys.objects where name = 'DoSome'))
drop proc DoSome
go
create proc DoSome(
@id varchar()
)
as
begin transaction
begin try
truncate table [dbo].[DBTestOne];
insert into DBTestOne values(@id,'','');
delete from DBTestOne where id=''
commit transaction
end try
begin catch
rollback transaction
end catch go
exec DoSome
  private static void DBNewMethod3(EFDB3Entities db)
{
Console.WriteLine("---------------------------------3. 测试根据指定条件查询数据(含输入参数)----------------------------------------");
int n = db.DoSome("");
if (n > )
{
Console.WriteLine("操作成功");
}
else
{
Console.WriteLine("没有更多数据进行处理");
} }

4. 带有输出参数

  if (exists (select * from sys.objects where name = 'GetT1Value'))
drop proc GetT1Value
go
create proc GetT1Value(
@t1 varchar(32),
@count int output
)
as
select @count=count(*) from DBTestOne where t1=@t1;
select * from DBTestOne where t1=@t1;
go
declare @myCount int;
exec GetT1Value '',@myCount output;
select @myCount as myCount;
   private static void DBNewMethod4(EFDB3Entities db)
{
Console.WriteLine("---------------------------------4. 测试查询含有输入和输出操作----------------------------------------");
//声明一下输出参数
ObjectParameter para1 = new ObjectParameter("XXX", SqlDbType.Int); var tList1 = db.GetT1Value("", para1).ToList();
//通过.Value获取输出参数的值。
var count = para1.Value; Console.WriteLine($"数量count为:{count}");
foreach (var item in tList1)
{
Console.WriteLine("id为:{0},t1为:{1},t2为:{2}", item.id, item.t1, item.t2);
} }

 PS:需要先声明ObjectParameter对象来存放输出参数,执行完后,通过.Value即可以获取输出参数,输出参数都是一个值,还没遇到集合的(PS:欢迎补充)。

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 

第四节: EF调用存储过程的通用写法和DBFirst模式子类调用的特有写法的更多相关文章

  1. ASP.NET MVC深入浅出(被替换) 第一节: 结合EF的本地缓存属性来介绍【EF增删改操作】的几种形式 第三节: EF调用普通SQL语句的两类封装(ExecuteSqlCommand和SqlQuery ) 第四节: EF调用存储过程的通用写法和DBFirst模式子类调用的特有写法 第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性) 第十节: EF的三种追踪

    ASP.NET MVC深入浅出(被替换)   一. 谈情怀-ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态 ...

  2. 第十四节: EF的三种模式(四) 之 原生正宗的 CodeFirst模式的默认约定

    一. 简介 1. 正宗的CodeFirst模式是不含有edmx模型,需要手动创建实体.创建EF上下文,然后生成通过代码来自动映射生成数据库. 2. 旨在:忘记SQL.忘记数据库. 3. 三类配置:On ...

  3. C# 连接Oracle,并调用存储过程(存在返回值),C# 调用sql存储过程

    1.获取Oracle表格信息 public OracleHelpers(string ConnStr) { ConnectionString = ConnStr; conn = new OracleC ...

  4. Mybatis学习总结(七)——调用存储过程

    一.返回select结果集 1.创建存储过程 DELIMITER // DROP PROCEDURE IF EXISTS proc_queryUser; CREATE PROCEDURE proc_q ...

  5. JDBC第二篇--【PreparedStatment、批处理、处理二进制、自动主键、调用存储过程、函数】

    这是我JDBC的第一篇 http://blog.csdn.net/hon_3y/article/details/53535798 1.PreparedStatement对象 PreparedState ...

  6. JDBC【PreparedStatment、批处理、处理二进制、自动主键、调用存储过程、函数】

    1.PreparedStatement对象 PreparedStatement对象继承Statement对象,它比Statement对象更强大,使用起来更简单 Statement对象编译SQL语句时, ...

  7. spring jdbctemplate调用存储过程,返回list对象

    注:本文来源于<  spring jdbctemplate调用存储过程,返回list对象 > spring jdbctemplate调用存储过程,返回list对象 方法: /** * 调用 ...

  8. Asp调用存储过程,command.CreateParameter 参数值的类型说明

    Asp调用存储过程,command.CreateParameter 参数值的类型说明 Asp调用各种存储过程,包括带参数,无参数,输入输出参数,带返回值等. 1,调用没有参数的存储过程 <% s ...

  9. python中子类调用父类的方法

    1子类调用父类构造方法 class Animal(object): def __init__(self): print("init Animal class~") def run( ...

随机推荐

  1. php $$可变变量理解

    //在变量前面加上两个$$,如$$name,这表示可变变量,可以动态的设置和使用,先设置一个普通变量,一个可变变量会获取了一个普通变量的值作为这个可变变量的变量名 $a = 'b'; $b = 'c' ...

  2. 记一个bug

    就在刚刚,测试叫我去看一个问题,有用户反应,在业务页面,出现了一部分重复的内容,而且点击按钮弹窗里,出现了只有个title,没有body的情况. 事情的现象就是这样.然后我就开始着手找原因了.首先声明 ...

  3. centos7下kubernetes(15。kubernetes-外网访问service)

    kubernetes提供了多种类型的service,默认是cluster IP ClusterIP cluster内部IP对外提供服务,只有cluster内的节点和pod可访问,这是默认的servic ...

  4. 【题解】P1119 灾后重建

    题目地址 理解Floyed的本质 Floyed的本质是动态规划. 在地K次循环中,Floyed算法枚举任意点对(X,Y),在这之前,K从未做过任何点对的中点.因此,可以利用K为中转的路径长度更新. 在 ...

  5. 多节点,多线程下发订单,使用zookeeper分布式锁机制保证订单正确接入oms系统

    假设订单下发, 采用单机每分钟从订单OrderEntry接口表中抓100单, 接入订单oms系统中. 由于双十一期间, 订单量激增, 导致订单单机每分钟100单造成, 订单积压. 所以采用多节点多线程 ...

  6. tcping ,一个好用的TCP端口检测工具

    1.常用的用法(windows) tcp -w 10 -t -d -i 5 -j --color 81.156.165.66 443 2. http模式 -u,与-h命令连用,每一行输出目标的url ...

  7. codeforces#1136 C. Nastya Is Transposing Matrices(找规律)

    题意:给出两个n*m的矩阵,每次操作可以让一个正方形矩阵行列交换.问,在无限次操作下,第一个矩阵能否变成第二个矩阵 分析:先把操作限定在2*2的矩阵中.这样对角线上的元素就可以随意交换.也就是说,如果 ...

  8. Django rest framework(8)---- 视图和渲染器

    django rest framework 之视图 序列化器    PagerSerialiser from rest_framework import serializers from api im ...

  9. java 虚拟机内存模型

    [声明] 欢迎转载,但请保留文章原始出处→_→ 文章来源:[http://www.cnblogs.com/smyhvae/p/4748392.html] 文章来源:[http://www.cnblog ...

  10. centos7之关于时间和日期以及时间同步的应用

    在CentOS 6版本,时间设置有date.hwclock命令,从CentOS 7开始,使用了一个新的命令timedatectl. 基本概念: 一.GMT.UTC.CST.DST 时间 UTC 整个地 ...