一. 背景
上一個章節,介紹了EF調用兩類SQL語句,主要是借助 ExecuteSqlCommand 和 SqlQuery 兩個方法來完成,在本章節主要是復習幾類存儲過程的寫法和對應的EF調用這幾類存儲過程的寫法,另外介紹EF的DBFirst模式的下EF存儲過程的特有寫法。
本章要達到以下幾個目標:
① 熟練掌握存儲過程的相關概念和幾類寫法(去復習)
② EF各種模式調用各種存儲過程的通用寫法(也是借助 ExecuteSqlCommand 和 SqlQuery )
③ EF的DBFirst模式事先映射好存儲過程,簡潔調用的寫法
二. EF調用存儲過程
EF調用存儲過程通用的寫法,分兩類:
① 對於查詢相關的存儲過程,調用 SqlQuery 方法
② 對於增刪改或其他的存儲過程,調用 ExecuteSqlCommand 方法
1. 不含任何參數(查詢類的存儲過程)
直接調用SqlQuery方法進行操作。
1 if (exists (select * from sys.objects where name = 'GetAll')) 2 drop proc GetAll 3 go 4 create proc GetAll 5 as 6 select * from TestOne; 7 8 -- 調用 9 exec GetAll;
1 private static void NewMethod(DbContext db) 2 { 3 Console.WriteLine("---------------------------------1. 測試查詢所有數據(不含輸入參數)----------------------------------------"); 4 List<TestOne> tList = db.Database.SqlQuery<TestOne>("GetAll").ToList(); 5 foreach (var item in tList) 6 { 7 Console.WriteLine("id為:{0},t1為:{1},t2為:{2}", item.id, item.t1, item.t2); 8 } 9 }
2. 含多個輸入參數(查詢類的存儲過程)
調用SqlQuery方法進行操作,傳入參數的使用要使用SqlParameter參數化的方式進行傳入,特別注意:調用時,存儲過程的名字后面的參數 必須按照SqlParameter中的先后順序來寫。
1 if (exists (select * from sys.objects where name = 'GetALLBy')) 2 drop proc GetALLBy 3 go 4 create proc GetALLBy( 5 @id varchar(32), 6 @t1 varchar(32) 7 ) 8 as 9 select * from TestOne where id=@id and t1=@t1; 10 11 exec GetALLBy @id='1',@t1='2';
1 private static void NewMethod2(DbContext db) 2 { 3 Console.WriteLine("---------------------------------2. 測試根據指定條件查詢數據(含輸入參數)----------------------------------------"); 4 SqlParameter[] para ={ 5 new SqlParameter("@id","1"), 6 new SqlParameter("@t1","txt1") 7 }; 8 //調用的時,存儲過程的名字后面的參數 必須按照SqlParameter中的先后順序來寫 9 List<TestOne> tList = db.Database.SqlQuery<TestOne>("GetALLBy @id,@t1", para).ToList(); 10 foreach (var item in tList) 11 { 12 Console.WriteLine("id為:{0},t1為:{1},t2為:{2}", item.id, item.t1, item.t2); 13 } 14 }
3. 增刪改的存儲過程(含1個輸入參數)
調用 ExecuteSqlCommand 方法來執行,針對輸入參數,要采用SqlParameter的方式來進行傳參數
1 if (exists (select * from sys.objects where name = 'DoSome')) 2 drop proc DoSome 3 go 4 create proc DoSome( 5 @id varchar(32) 6 ) 7 as 8 begin transaction 9 begin try 10 truncate table [dbo].[TestOne]; 11 insert into TestOne values(@id,'1','2'); 12 delete from TestOne where id='2' 13 commit transaction 14 end try 15 begin catch 16 rollback transaction 17 end catch 18 19 exec DoSome 1
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 > 0) { Console.WriteLine("操作成功"); } else { Console.WriteLine("沒有更多數據進行處理"); } }
4. 帶輸出參數的存儲過程的調用
1 GO 2 if (exists (select * from sys.objects where name = 'GetT1Value')) 3 drop proc GetT1Value 4 go 5 create proc GetT1Value( 6 @t1 varchar(32), 7 @count int output 8 ) 9 as 10 select @count=count(*) from TestOne where t1=@t1; 11 select * from TestOne where t1=@t1; 12 go 13 declare @myCount int; 14 exec GetT1Value '111',@myCount output; 15 select @myCount as myCount;
1 private static void NewMethod4(DbContext db) 2 { 3 Console.WriteLine("---------------------------------4. 測試查詢含有輸入和輸出操作----------------------------------------"); 4 //把輸出參數單獨拿出來聲明 5 SqlParameter para1 = new SqlParameter("@t2", SqlDbType.Int); 6 para1.Direction = ParameterDirection.Output; 7 //把輸出參數放到數組里 8 SqlParameter[] para2 ={ 9 new SqlParameter("@t1","111"), 10 para1 11 }; 12 var tList1 = db.Database.SqlQuery<TestOne>("exec GetT1Value @t1,@t2 out", para2).ToList(); 13 //通過輸出參數在數組中的位置來獲取返回值。 14 var count = para2[1].Value; 15 16 Console.WriteLine($"數量count為:{count}"); 17 foreach (var item in tList1) 18 { 19 Console.WriteLine("id為:{0},t1為:{1},t2為:{2}", item.id, item.t1, item.t2); 20 } 21 22 }
PS:這種調用方式,需要先聲明一下輸出類型,然后把輸出參數放到SqlParameter這個數組里,執行完后,通過數值下標.Value來獲取這個返回值。(和DBFirst模式下調用有所不同)
三. DBFirst模式快捷調用存儲過程
前面介紹的調用存儲過程的方法是通用模式,無論EF的哪種模式都可以使用,這里將介紹DBFirst模式的快捷調用,原理即創建的時候將存儲過程映射進來了,所以可以直接調用。如下圖:
1. 不含任何參數(查詢類存儲過程)
1 -- 1.無參存儲過程(查詢) 2 if (exists (select * from sys.objects where name = 'GetAll')) 3 drop proc GetAll 4 go 5 create proc GetAll 6 as 7 select * from DBTestOne; 8 9 -- 調用 10 exec GetAll;
1 private static void DBNewMethod(EFDB3Entities db) 2 { 3 Console.WriteLine("---------------------------------1. 測試查詢所有數據(不含輸入參數)----------------------------------------"); 4 var tList = db.GetAll().ToList(); 5 foreach (var item in tList) 6 { 7 Console.WriteLine("id為:{0},t1為:{1},t2為:{2}", item.id, item.t1, item.t2); 8 } 9 }
2. 含多個輸入參數(查詢類存儲過程)
1 --2. 有參數的存儲過程(查詢) 2 if (exists (select * from sys.objects where name = 'GetALLBy')) 3 drop proc GetALLBy 4 go 5 create proc GetALLBy( 6 @id varchar(32), 7 @t1 varchar(32) 8 ) 9 as 10 select * from DBTestOne where id=@id and t1=@t1; 11 12 exec GetALLBy @id='1',@t1='2';
1 private static void DBNewMethod2(EFDB3Entities db) 2 { 3 Console.WriteLine("---------------------------------2. 測試根據指定條件查詢數據(含輸入參數)----------------------------------------"); 4 var tList = db.GetALLBy("11", "1").ToList(); 5 foreach (var item in tList) 6 { 7 Console.WriteLine("id為:{0},t1為:{1},t2為:{2}", item.id, item.t1, item.t2); 8 } 9 }
3. 增刪改存儲過程(含1個輸入參數)
1 --3. 增刪改的一組過程 2 if (exists (select * from sys.objects where name = 'DoSome')) 3 drop proc DoSome 4 go 5 create proc DoSome( 6 @id varchar(32) 7 ) 8 as 9 begin transaction 10 begin try 11 truncate table [dbo].[DBTestOne]; 12 insert into DBTestOne values(@id,'1','2'); 13 delete from DBTestOne where id='2' 14 commit transaction 15 end try 16 begin catch 17 rollback transaction 18 end catch 19 20 go 21 exec DoSome 1
1 private static void DBNewMethod3(EFDB3Entities db) 2 { 3 Console.WriteLine("---------------------------------3. 測試根據指定條件查詢數據(含輸入參數)----------------------------------------"); 4 int n = db.DoSome("33"); 5 if (n > 0) 6 { 7 Console.WriteLine("操作成功"); 8 } 9 else 10 { 11 Console.WriteLine("沒有更多數據進行處理"); 12 } 13 14 }
4. 帶有輸出參數
1 if (exists (select * from sys.objects where name = 'GetT1Value')) 2 drop proc GetT1Value 3 go 4 create proc GetT1Value( 5 @t1 varchar(32), 6 @count int output 7 ) 8 as 9 select @count=count(*) from DBTestOne where t1=@t1; 10 select * from DBTestOne where t1=@t1; 11 go 12 declare @myCount int; 13 exec GetT1Value '111',@myCount output; 14 select @myCount as myCount;
1 private static void DBNewMethod4(EFDB3Entities db) 2 { 3 Console.WriteLine("---------------------------------4. 測試查詢含有輸入和輸出操作----------------------------------------"); 4 //聲明一下輸出參數 5 ObjectParameter para1 = new ObjectParameter("XXX", SqlDbType.Int); 6 7 var tList1 = db.GetT1Value("1", para1).ToList(); 8 //通過.Value獲取輸出參數的值。 9 var count = para1.Value; 10 11 Console.WriteLine($"數量count為:{count}"); 12 foreach (var item in tList1) 13 { 14 Console.WriteLine("id為:{0},t1為:{1},t2為:{2}", item.id, item.t1, item.t2); 15 } 16 17 }
PS:需要先聲明ObjectParameter對象來存放輸出參數,執行完后,通過.Value即可以獲取輸出參數,輸出參數都是一個值,還沒遇到集合的(PS:歡迎補充)。
!
- 作 者 : Yaopengfei(姚鵬飛)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 聲 明1 : 本人才疏學淺,用郭德綱的話說“我是一個小學生”,如有錯誤,歡迎討論,請勿謾罵^_^。
- 聲 明2 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。