一步一步學Linq to sql(五):儲存過程
普通儲存過程
首先在查詢分析器執行下面的程式碼來建立一個儲存過程:
createprocsp_singleresultset
as
setnocounton
select*fromcustomers
然後開啟IDE的伺服器資源管理器,之前我們從表中拖動表到dbml設計檢視,這次我們從儲存過程中找到剛才建立的儲存過程,然後拖動到設計檢視。在方法面板中可以看到已經建立了一個sp_singleresultset的方法,如下圖:
然後開啟Northwind.designer.cs,可以找到下面的程式碼:
[Function(Name="dbo.sp_singleresultset")]
publicISingleResultsp_singleresultset()
{
IExecuteResultresult = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())));
return((ISingleResult)(result.ReturnValue));
}
我們可以發現,IDE為這個儲存過程單獨生成了返回結果集的實體定義,你可能會覺得很奇怪,IDE怎麼知道這個儲存過程將會返回哪些資料那?其實,在把儲存過程拖拽入dbml設計檢視的時候,IDE就執行了類似下面的命令:
SET FMTONLY ON;
exec Northwind.dbo.sp_singleresultset
SET FMTONLY OFF;
這樣就可以直接獲取儲存過程返回的元資料而無須執行儲存過程。
其實我們儲存過程返回的就是顧客表的資料,如果你覺得為儲存過程單獨設定結果集實體有些浪費的話可以在儲存過程的屬性視窗中調整返回型別從“自動生成的型別”到Customer,不過以後你只能通過刪除方法面板中的儲存過程,然後重新新增來還原到“自動生成的型別”。下面,我們可以寫如下的Linq to object程式碼進行查詢:
var單結果集儲存過程=
fromc inctx.sp_singleresultset()
wherec.CustomerID.StartsWith("A")
selectc;
在這裡確實是Linq to object的,因為查詢句法不會被整句翻譯成SQL,而是從儲存過程的返回物件中再去對物件進行查詢。SQL程式碼如下:
EXEC @RETURN_VALUE = [dbo].[sp_singleresultset]
-- @RETURN_VALUE: Output Int32 (Size = 0; Prec = 0; Scale = 0) []
帶引數的儲存過程
建立如下儲存過程:
createproc[dbo].[sp_withparameter]
@customerid nchar(5),
@rowcount intoutput
as
setnocounton
[email protected] =(selectcount(*)fromcustomers wherecustomerid [email protected])
使用同樣的方法生成儲存過程方法,然後使用下面的程式碼進行測試:
int? rowcount = -1;
ctx.sp_withparameter("", refrowcount);
Response.Write(rowcount);
ctx.sp_withparameter("ALFKI", refrowcount);
Response.Write(rowcount);
結果輸出了“01”。說明ID為“”的顧客數為0,而ID為“ALFKI”的顧客數為1。儲存過程的輸出引數被封裝成了ref引數,對於C#語法來說非常合情合理。SQL程式碼如下:
EXEC @RETURN_VALUE = [dbo].[sp_withparameter] @customerid = @p0, @rowcount = @p1 OUTPUT
-- @p0: Input StringFixedLength (Size = 5; Prec = 0; Scale = 0) []
-- @p1: InputOutput Int32 (Size = 0; Prec = 0; Scale = 0) [-1]
-- @RETURN_VALUE: Output Int32 (Size = 0; Prec = 0; Scale = 0) []
帶返回值的儲存過程
再來建立第三個儲存過程:
createproc[dbo].[sp_withreturnvalue]
@customerid nchar(5)
as
setnocounton
ifexists(select1 fromcustomers wherecustomerid [email protected])
return101
else
return100
生成方法後,可以通過下面的程式碼進行測試:
Response.Write(ctx.sp_withreturnvalue(""));
Response.Write(ctx.sp_withreturnvalue("ALFKI"));
執行後程序輸出“100101”
多結果集的儲存過程
再來建立一個多結果集的儲存過程:
createproc[dbo].[sp_multiresultset]
as
setnocounton
select*fromcustomers
select*fromemployees
找到生成的儲存過程方法:
[Function(Name="dbo.sp_multiresultset")]
publicISingleResultsp_multiresultset()
{
IExecuteResultresult = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())));
return((ISingleResult)(result.ReturnValue));
}
由於現在的VS2008會把多結果集儲存過程識別為單結果集儲存過程(只認識第一個結果集),我們只能對儲存過程方法多小動手術,修改為:
[Function(Name="dbo.sp_multiresultset")]
[ResultType(typeof(Customer))]
[ResultType(typeof(Employee))]
publicIMultipleResultssp_multiresultset()
{
IExecuteResultresult = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())));
return(IMultipleResults)(result.ReturnValue);
}
然後使用下面的程式碼測試:
var多結果集儲存過程= ctx.sp_multiresultset();
varCustomers = 多結果集儲存過程.GetResult();
varEmployees = 多結果集儲存過程.GetResult();
GridView1.DataSource = fromemp inEmployees whereemp.FirstName.Contains("A") selectemp;
GridView1.DataBind();
GridView2.DataSource = fromc inCustomers wherec.CustomerID.StartsWith("A") selectc;
GridView2.DataBind();
使用儲存過程新增資料
儲存過程除了可以直接呼叫之外,還可以用於實體的增刪改操作。還記得在《一步一步學Linq to sql(三):增刪改》中建立的留言簿程式嗎?下面我們就來改造這個程式,使用儲存過程而不是系統生成的SQL實現實體增刪改。首先,我們建立下面的儲存過程
createprocsendmessage
@username varchar(50),
@message varchar(500)
as
insertintotbguestbook
(id,username,posttime,[message],isreplied,reply)
values
(newid(),@username,getdate(),@message,0,')
然後,開啟留言簿dbml,把儲存過程從伺服器資源管理器拖拽到設計檢視上。右鍵點選tbGuestBook實體類,選擇配置行為。如下圖,為插入操作選擇剛才建立的儲存過程方法,並進行引數匹配:
由於我們的儲存過程只接受2個引數,相應修改以下建立留言的按鈕處理事件:
protectedvoidbtn_SendMessage_Click(objectsender, EventArgse)
{
tbGuestBookgb = newtbGuestBook();
gb.UserName = tb_UserName.Text;
gb.Message = tb_Message.Text;
ctx.tbGuestBooks.Add(gb);
ctx.SubmitChanges();
SetBind();
}
執行程式後可以發現,在提交修改的時候呼叫了下面的SQL:
EXEC @RETURN_VALUE = [dbo].[sendmessage] @username = @p0, @message = @p1
-- @p0: Input AnsiString (Size = 5; Prec = 0; Scale = 0) [zhuye]
-- @p1: Input AnsiString (Size = 11; Prec = 0; Scale = 0) [new message]
-- @RETURN_VALUE: Output Int32 (Size = 0; Prec = 0; Scale = 0) []
使用儲存過程刪除資料
建立如下儲存過程:
createprocdelmessage
@id uniqueidentifier
as
deletetbguestbook [email protected]
按照前面的步驟生成儲存過程方法,併為刪除操作執行這個儲存過程方法。在選擇引數的時候我們可以看到,ID分當前值和原始值,我們選擇當前值即可,如下圖:
無須改動任何邏輯程式碼,進行刪除留言操作後可以跟蹤到下面的SQL:
EXEC @RETURN_VALUE = [dbo].[delmessage] @id = @p0
-- @p0: Input Guid (Size = 0; Prec = 0; Scale = 0) [9e3c5ee3-2575-458e-899d-4b0bf73e0849]
-- @RETURN_VALUE: Output Int32 (Size = 0; Prec = 0; Scale = 0) []
使用儲存過程更改資料
建立如下儲存過程:
createprocreplymessage
@id uniqueidentifier,
@reply varchar(500)
as
updatetbguestbook [email protected],isreplied=1 [email protected]
由於更新的時候並不會更新主鍵,所以我們可以為兩個引數都指定當前值。回覆留言後可以跟蹤到下面的SQL:
EXEC @RETURN_VALUE = [dbo].[replymessage] @id = @p0, @reply = @p1
-- @p0: Input Guid (Size = 0; Prec = 0; Scale = 0) [67a69d0f-a88b-4b22-8939-fed021eb1cb5]
-- @p1: Input AnsiString (Size = 6; Prec = 0; Scale = 0) [464456]
-- @RETURN_VALUE: Output Int32 (Size = 0; Prec = 0; Scale = 0) []
假設有這樣一種應用,我們需要修改留言簿中不合法的使用者名稱:
createprocmodiusername
@oldusername varchar(50),
@newusername varchar(50)
as
updatetbguestbook [email protected] whereusername [email protected]
有個網友起名叫“admin”,我們要把所有這個名字修改為“notadmin”。那麼,可以如下圖設定update操作:
然後執行下面的測試程式碼:
varmessages = fromgb inctx.tbGuestBooks
selectgb;
foreach(vargb inmessages)
{
if(gb.UserName == "admin")
gb.UserName = "notadmin"
}
執行程式後能跟蹤到下面的SQL:
SELECT [t0].[ID], [t0].[UserName], [t0].[PostTime], [t0].[Message], [t0].[IsReplied], [t0].[Reply]
FROM [dbo].[tbGuestBook] AS [t0]
EXEC @RETURN_VALUE = [dbo].[modiusername] @oldusername = @p0, @newusername = @p1
-- @p0: Input AnsiString (Size = 5; Prec = 0; Scale = 0) [admin]
-- @p1: Input AnsiString (Size = 8; Prec = 0; Scale = 0) [notadmin]
-- @RETURN_VALUE: Output Int32 (Size = 0; Prec = 0; Scale = 0) []
到這裡,你應該能明白當前值和原始值的含義了吧。
本文轉自
http://www.cnblogs.com/lovecherry/archive/2007/08/18/860935.html
相關推薦
一步一步學Linq to sql(五):儲存過程
導讀: 普通儲存過程 首先在查詢分析器執行下面的程式碼來建立一個儲存過程: createprocsp_singleresultset as setnocounton select*fromcustomers 然後開啟IDE的伺服器
跟廠長學PHP7內核(五):一步步分析生命周期之模塊初始化階段
hle 持久 globals .post lean nco ror sign trie 上篇我們講到了模塊初始化階段,並得知它是由php_module_startup函數來實現的。該階段的主要作用是初始化變量、常量;註冊各種函數,比如工具、詞法、語法函數等;解析配置文件;
[神經網絡]一步一步使用Mobile-Net完成視覺識別(五)
arc del img fault model coord graph 處理 mobile 1.環境配置 2.數據集獲取 3.訓練集獲取 4.訓練 5.調用測試訓練結果 6.代碼講解 本文是第五篇,講解如何調用測試訓練結果。 上一篇中我們輸出了訓練的模型,這一篇中我們通
從零開始學 Web 之 Ajax(五)同步異步請求,數據格式
遊記 document 空閑 name center 20px 實現 resp 也會 大家好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公眾號:Web前端之
小白學 Python 資料分析(2):Pandas (一)概述
人生苦短,我用 Python 前文傳送門: 小白學 Python 資料分析(1):資料分析基礎 概覽 首先還是幾個官方連結放一下: Pandas 官網:https://pandas.pydata.org/ Pandas 中文網:https://www.pypandas.cn/ Pandas Githu
小白學 Python 資料分析(12):Pandas (十一)資料透視表(pivot_table)
![](https://cdn.geekdigging.com/python/spider-blog/Python_logo.jpg) > 人生苦短,我用 Python 前文傳送門: [小白學 Python 資料分析(1):資料分析基礎](https://www.geekdigging.com/2020
小白學 Python 資料分析(16):Matplotlib(一)座標系
![](https://cdn.geekdigging.com/python/spider-blog/Python_logo.jpg) > 人生苦短,我用 Python 前文傳送門: [小白學 Python 資料分析(1):資料分析基礎](https://www.geekdigging.com/2020
從LINQ開始之LINQ to Objects(上)
opp 一對多 ear bool 元素 代碼 可用 etime 語法 LINQ概述 LINQ,語言集成查詢(Language Integrated Query),它允許使用C#或VB代碼以查詢數據庫相同的方式來操作不同的數據源。 LINQ體系結構 從上圖可以看出,LI
從LINQ開始之LINQ to Objects(下)
方法 current sel virtual start .com 代碼 命名空間 edt 前言 上一篇《從LINQ開始之LINQ to Objects(上)》主要介紹了LINQ的體系結構、基本語法以及LINQ to Objects中標準查詢操作符的使用方法。本篇則主要討
七步從AngularJS菜鳥到專家(7):Routing
們的 cat idt pan post 好的 書簽 廣播電臺 快速 這是"AngularJS – 七步從菜鳥到專家"系列的第七篇。在第一篇,我們展示了如何開始搭建一個AngularaJS應用。在第四、五篇我們討論了Angular內建的directives。上一篇了解了se
C#復習筆記(4)--C#3:革新寫代碼的方式(查詢表達式和LINQ to object(上))
類型 否則 表達 數據集 clas 階段 邏輯 變量 RR 查詢表達式和LINQ to object(上) 本章內容: 流式處理數據和延遲執行序列 標準查詢操作符和查詢表達式轉換 範圍變量和透明標識符 投影、過濾和排序 聯接和分組 選擇要使用的語法 LINQ中的概
C#復習筆記(4)--C#3:革新寫代碼的方式(查詢表達式和LINQ to object(下))
標識 all 麻煩 linq with write mar sel img 查詢表達式和LINQ to object(下) 接下來我們要研究的大部分都會涉及到透明標識符 let子句和透明標識符 let子句不過是引入了一個新的範圍變量。他的值是基於其他範圍變量的。let 標識
JPA(五):映射關聯關系------映射單向多對一的關聯關系
span AS 127.0.0.1 mysql5 單向 cti isa 嘗試 sequence 映射單向多對一的關聯關系 新建Customer.java: package com.dx.jpa.singlemanytoone; import java.ut
python手記(五):requests寫爬蟲(一):爬蟲簡介
上次將python的圖片處理庫簡單寫了下,也就基本處於玩的地步。哈哈,蠻嘲諷的,這次我嘗試著寫下爬蟲,有多深肯定是不敢保證的,畢竟能力有限。但是我會盡量去從原理上把爬蟲的東西說明白一些。讓大家有個直觀的認識,最後能自己寫出個簡單的定向小爬蟲,爬個小說,爬個圖片,爬首歌曲什麼的
java基礎(五):for迴圈和一維陣列
import java.util.Random; import java.util.Scanner; class DouDiZhu {public static void main(String[] args) {//1. 生成54張牌 -- 不需要引數,返回值String[]String[] pic =
Mina、Netty、Twisted一起學(五):整合protobuf
ear ive obj con line 谷歌 encode etc 創建 protobuf是谷歌的Protocol Buffers的簡稱,用於結構化數據和字節碼之間互相轉換(序列化、反序列化),一般應用於網絡傳輸,可支持多種編程語言。protobuf怎樣使用這裏不再介紹
oracle sql 基礎(五):數據定義語言(創建和管理序列、索引、同義詞)
aps span 最小值 into 全表掃描 條件 creat 返回 ext 許多應用程序要求使用唯一的數字作為主鍵的值,你即可以在應用程序中構建代碼來處理這種需求,也可以用一個序列來產生唯一的數字。如果你想要增進某些查詢的性能,你應該考慮創建一個索引,你也可
SQL基礎(五):SQL函數
註釋 返回 訪問量 ces intro div group by -1 rownum 一、SQL Aggregate 函數: SQL Aggregate 函數計算從列中取得的值,返回一個單一的值。 1、AVG() 函數 AVG() 函數返回數值列的平均值。 語法
SQL Server 2005中的分區表(五):添加一個分區
eat 查詢 sch 另一個 rom 原創 查看 copyto art 所謂天下大事,分久必合,合久必分,對於分區表而言也一樣。前面我們介紹過如何刪除(合並)分區表中的一個分區,下面我們介紹一下如何為分區表添加一個分區。 為分區表添加一個分區,這種情況是時常會
MyBatis的動態SQL(五)
pan 需要 9.png ack bat 鏈接 where In 標簽 用於實現動態SQL的元素主要有iftrimwheresetchoose(when、otherwise)foreach if標簽 Where標簽 Sql後面添加: where 1=1 ,那