-
ADO.NET是.net操作數(shù)據(jù)庫(kù)的一個(gè)模塊的總稱
ADO,NET擁有自己的接口樱哼,基本.net體系結(jié)構(gòu)
我們通過(guò)他來(lái)操作數(shù)據(jù)庫(kù)箍铲,對(duì)數(shù)據(jù)庫(kù)進(jìn)行增刪改查的操作
還可以執(zhí)行sql調(diào)用SQL里面的函數(shù)御吞,執(zhí)行存儲(chǔ)過(guò)程等等
我們很多大型的業(yè)務(wù)系統(tǒng)都是離不開(kāi)數(shù)據(jù)庫(kù)茁计,我們需要把一些數(shù)據(jù)固化到本地码荔,并且想要方便查找的話砸脊,那么就需要數(shù)據(jù)庫(kù)了
-
ADO主要就是提供一些對(duì)象是偷,這些對(duì)象就是封裝了一些操作數(shù)據(jù)庫(kù)的一些方法拳氢,比如Connection,Command蛋铆,DataSet馋评,DataReader,他們每個(gè)都有自己的功能刺啦。
Connection是用來(lái)對(duì)數(shù)據(jù)庫(kù)進(jìn)行連接留特,Command主要是用來(lái)執(zhí)行SQL的命令等禽炬,DataSet他其實(shí)是一個(gè)數(shù)據(jù)的集合关面,它是對(duì)數(shù)據(jù)庫(kù)進(jìn)行一個(gè)抽象,我們操作這個(gè)DataSet就好像是操作數(shù)據(jù)一樣横蜒, DataSet里面就包含DataTable(表) DataRow對(duì)應(yīng)表中的一條記錄糊渊,DataAdapter(適配器)右核,有了ADO.NET基礎(chǔ)后,我們才能開(kāi)發(fā)一些更強(qiáng)大的業(yè)務(wù)系統(tǒng)渺绒,包括我們的網(wǎng)站都是離不開(kāi)數(shù)據(jù)庫(kù)的
DataSet:非連接核心組件贺喝,獨(dú)立于任何數(shù)據(jù)源的數(shù)據(jù)訪問(wèn)
DataProvider(數(shù)據(jù)提供程序):用于連接數(shù)據(jù)庫(kù),執(zhí)行命令宗兼,檢索結(jié)果
SQLServer數(shù)據(jù)提供程序: System.Data.SqlClient命名空間
OLEDB數(shù)據(jù)提供程序:System.Data.oledb命名空間
ODBC數(shù)據(jù)提供程序:Systen.Data.odbc命名空間
Oracle數(shù)據(jù)提供程序:System.Data.OraceClient命名空間
Connection:提供與數(shù)據(jù)源的連接 SqlConnection
Command:執(zhí)行數(shù)據(jù)庫(kù)命令的對(duì)象 SqlCommand
DataReader:從數(shù)據(jù)源中快速的躏鱼,只讀的數(shù)據(jù)流 SqlDataReader
DataAdapter:提供DataSet對(duì)象與數(shù)據(jù)源的橋梁,它可以從數(shù)據(jù)源中執(zhí)行我們的T-SQL命令针炉,將數(shù)據(jù)填充到DataSet中去挠他,它的基本操作也是基于Command對(duì)象的,比如說(shuō)Fill方法篡帕,就是把數(shù)據(jù)填充到DataSet當(dāng)中去殖侵,比如說(shuō)UPDATE方法,可以更改DataSet中的數(shù)據(jù)等等
- ORM框架:EF镰烧,Mybatis等 linq to entity等
數(shù)據(jù)庫(kù)連接Connections
- ADO.NET訪問(wèn)數(shù)據(jù)的步驟:
1.連接數(shù)據(jù)庫(kù)
2.打開(kāi)連接
3.創(chuàng)建執(zhí)行命令對(duì)象(創(chuàng)建命令)
4.執(zhí)行命令
5.關(guān)閉連接
SqlConnection DbConnection 抽象基類拢军,不能被實(shí)例化
- 抽象基類:抽象類(abstract base class,ABC)就是類里定義了純虛成員函數(shù)的類。純虛函數(shù)一般只提供了接口怔鳖,并不會(huì)做具體實(shí)現(xiàn)(雖然可以)茉唉,實(shí)現(xiàn)由它的派生類去重寫。抽象類不能被實(shí)例化(不能創(chuàng)建對(duì)象),通常是作為基類供子類繼承度陆,子類中重寫虛函數(shù)艾凯,實(shí)現(xiàn)具體的接口。簡(jiǎn)言之懂傀,ABC描述的是至少使用一個(gè)純虛函數(shù)的接口趾诗,從ABC派生出的類將根據(jù)派生類的具體特征,使用常規(guī)虛函數(shù)來(lái)實(shí)現(xiàn)這種接口蹬蚁。
為什么使用連接池恃泪?
非常耗時(shí)耗力的一件事。需要經(jīng)歷幾個(gè)階段犀斋,建立物理通過(guò)贝乎,與服務(wù)器初次握手,分析連接字符串叽粹,身份驗(yàn)證览效,運(yùn)行檢查等等。球榆。朽肥。
相當(dāng)?shù)穆L(zhǎng)復(fù)雜禁筏。改進(jìn):是否重復(fù)利用已經(jīng)有的連接持钉?這就是使用連接池的原因。連接池是什么篱昔?
是一個(gè)存放了一定數(shù)量的與數(shù)據(jù)庫(kù)服務(wù)器的物理連接的容器
在需要用的時(shí)候每强,在容器里面取出一條空閑的連接,而不是創(chuàng)建一條新的連接州刽。作用:減少了連接數(shù)據(jù)庫(kù)的開(kāi)銷空执,從而提高應(yīng)用程序的性能
分類:類別區(qū)分,同一時(shí)刻統(tǒng)一應(yīng)用程序域可以有不同類型的連接池穗椅。
什么來(lái)標(biāo)識(shí)區(qū)分的呢:-------- 進(jìn)程辨绊、應(yīng)用程序域、連接字符串匹表、window標(biāo)識(shí) 共同組成的簽名來(lái)標(biāo)識(shí)區(qū)分门坷,
對(duì)同一程序域來(lái)說(shuō),由“連接字符串”來(lái)區(qū)分袍镀。打開(kāi)一條連接默蚌,如果這條連接類型簽名與現(xiàn)有的連接不匹配,就會(huì)創(chuàng)建一個(gè)新的連接池苇羡,反之绸吸,則不會(huì)和創(chuàng)建,他們會(huì)共用同一個(gè)連接池。如何分配連接
根據(jù)連接請(qǐng)求的類型锦茁,找到與它相匹配的連接池攘轩,盡力的分配一條空閑的連接。
有空閑的連接時(shí)码俩,返回這條連接
如果已經(jīng)用完撑刺,就會(huì)創(chuàng)建一個(gè)新的連接添加到連接池中,如果已達(dá)到最大連接數(shù)握玛,等待够傍,直達(dá)有空閑的連接可用移除無(wú)效連接
不能正確的連接上數(shù)據(jù)庫(kù)的連接。而連接池存儲(chǔ)的與數(shù)據(jù)庫(kù)的連接數(shù)量是有限的
無(wú)效連接應(yīng)當(dāng)移除挠铲。不移除會(huì)浪費(fèi)連接池空間冕屯,連接池管理器會(huì)處理無(wú)效連接的移除問(wèn)題回收連接
使用完的連接是如何釋放的?應(yīng)當(dāng)立即關(guān)閉或釋放拂苹,conn對(duì)象的Close方法或Diospose方法安聘,連接回到連接池-
測(cè)試連接池的存在
Ado.Net默認(rèn)是啟用連接池的
連接字符串是可以控制連接池的行為
1.三個(gè)屬性
Max Pool Size:最大連接數(shù) 100
Min Pool Size: 最小連接數(shù) 0
Pooling :是否啟用連接池 true false
-
啟用連接池與不啟用連接池性能差很多
image.png
循環(huán)5000次連接,不啟用連接池韓式10000多ms瓢棒,啟用連接池耗時(shí)30ms浴韭!這就是差距
-
SqlCommand介紹
是一個(gè)執(zhí)行數(shù)據(jù)庫(kù)命令的對(duì)象
-
重要屬性
- Connection:SqlCommand對(duì)象使用的SqlConnection - CommandText:獲取或設(shè)置要執(zhí)行的T-SQL語(yǔ)句或存儲(chǔ)過(guò)程 - CommandType:CommandType.Text --執(zhí)行的是一個(gè)Sql語(yǔ)句 CommandType.StoredProcedure --執(zhí)行的是一個(gè)存儲(chǔ)過(guò)程 - Parameters:SqlCommand對(duì)象的命令參數(shù)集合 空集合 - Transaction:獲取或設(shè)置要在其中執(zhí)行的事務(wù)
-
Command對(duì)象的創(chuàng)建
-
Command執(zhí)行方法
cmd.ExecuteNonQuery(); cmd.ExecuteScalar(); cmd.ExecuteReader();
-
ExecuteNonQuery方法介紹
執(zhí)行T-SQL語(yǔ)句或存儲(chǔ)過(guò)程,并返回受影響的行數(shù) 執(zhí)行的命令類型:插入脯宿、更新念颈、刪除操作----DML數(shù)據(jù)操作語(yǔ)言
-
ExcuteScalar方法介紹 查詢------DQL 數(shù)據(jù)查詢語(yǔ)言 ,返回的是一個(gè)值 object
//執(zhí)行的是查詢語(yǔ)句或者存儲(chǔ)過(guò)程连霉,返回的是查詢結(jié)果集中的第一行第一列的值榴芳,忽略其他行或列 //適用:作查詢,返回一個(gè)值跺撼,記錄數(shù) 數(shù)據(jù)運(yùn)算而出的結(jié)果 //命令類型:查詢------DQL 數(shù)據(jù)查詢語(yǔ)言 //共有的條件:conn狀態(tài) 必須是open //連接使用原則:最晚打開(kāi)窟感,最早關(guān)閉 //統(tǒng)計(jì)有多少條記錄 SELECT COUNT(0) FROM dbo.Info; 無(wú)論count的值是多少,0還是1歉井,返回的都是數(shù)據(jù)量一共有多少條數(shù)據(jù) insert into (DeptInfos) values (' 采購(gòu)部')柿祈;select @@identity;
-
ExcuteReader() 查詢 返回的是一個(gè)對(duì)象:SqlDataReader
返回的是數(shù)據(jù)閱讀器,返回的是一種數(shù)據(jù)流的方式哩至,適用于數(shù)據(jù)量比較少的情況下躏嚎,他讀取的速度比較快,比較高效憨募,而且耗用內(nèi)存小 SqlDataReader是一個(gè)數(shù)據(jù)流紧索,是一種實(shí)時(shí)讀取的方式。理解成數(shù)據(jù)庫(kù)中的游標(biāo)菜谣,就像指針一樣珠漂。比如說(shuō)就讀第一條晚缩,指針就讀到第一條,把第一條數(shù)據(jù)以流的形式發(fā)送到調(diào)用端媳危,然后讀取出來(lái)荞彼,讀取完過(guò)后,指針會(huì)前進(jìn)到下一條數(shù)據(jù)待笑。讀取方式比較固定鸣皂,不靈活。是一種只能往下繼續(xù)讀取暮蹂,不能往后讀取寞缝。 //適用:只是讀取數(shù)據(jù),不做修改的情況下仰泻,適用于數(shù)據(jù)量比較小的情況下荆陆,因?yàn)槭菚?huì)一直占著連接的
-
SqlParamter
定義:表示SqlComand對(duì)象的參數(shù),或與DataSet中列的映射
常用屬性:
DbType參數(shù)的SqlType(數(shù)據(jù)類型 數(shù)據(jù)庫(kù)的類型而言)
Direction 參數(shù)的類型:輸入?yún)?shù)集侯、輸出參數(shù)被啼、輸入輸出參數(shù)、返回值參數(shù)
ParamterName 參數(shù)的名稱
Size 最大大小
Value 參數(shù)的值
SqlValue 作為SQL類型的值的參數(shù)的值-
參數(shù)的構(gòu)造方法
{ //參數(shù)的構(gòu)造方法 //1.參數(shù) SqlParameter para1 = new SqlParameter(); para1.ParameterName = "@Name";//參數(shù)名 para1.SqlDbType = SqlDbType.VarChar;//數(shù)據(jù)類型 para1.Value = "admin";//參數(shù)值 para1.Size = 20;//大小 //2.參數(shù)名棠枉,值 SqlParameter para2 = new SqlParameter("@Sex", "男"); //3.參數(shù)名浓体,SqlDbType SqlParameter para3 = new SqlParameter("@DeptId", SqlDbType.Int); para3.Size = 4; para3.Value = 3; //4.參數(shù)名 類型 大小 SqlParameter para4 = new SqlParameter("@Pwd", SqlDbType.VarChar, 50); para4.Value = "123456"; //5.參數(shù)名 類型 大小 源列名(對(duì)應(yīng)DataTable中的列名) SqlParameter para5 = new SqlParameter("@UserName", SqlDbType.VarChar, 20, "Name"); }
-
參數(shù)的作用
不帶任何條件,不是通過(guò)參數(shù)傳遞辈讶,是拼接的sql語(yǔ)句命浴,生成sql語(yǔ)句,具體的值 拼接sql:容易被sql注入----鉆空子 //--把sql語(yǔ)句給注釋掉了荞估,所以就會(huì)查詢出此表中所有的數(shù)據(jù)咳促,后果很嚴(yán)重 string sql = "select Name,Sex from Info where 1=1 -- Id="+userId+""; 單引號(hào)轉(zhuǎn)義的問(wèn)題:比如說(shuō) linqin 和 lin‘qin ‘linqin’不會(huì)報(bào)錯(cuò) ‘lin‘qin’就會(huì)報(bào)錯(cuò) static void Main(string[] args) { string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString; using (SqlConnection conn = new SqlConnection(connStr)) { //int userId = int.Parse(Console.ReadLine()); //--把sql語(yǔ)句給注釋掉了,所以就會(huì)查詢出此表中所有的數(shù)據(jù)勘伺,后果很嚴(yán)重 //string sql = "select Name,Sex from Info where 1=1 -- Id="+userId+""; //SqlCommand cmd = new SqlCommand("", conn); //參數(shù):不僅僅可以解決SQL注入,還可以解決轉(zhuǎn)義的問(wèn)題 string sql = "select Sex from Info where Name = @userName"; SqlCommand cmd = new SqlCommand(sql, conn); ////參數(shù)化sql語(yǔ)句中使用的是輸入?yún)?shù) ////cmd.Parameters.Add(new SqlParameter("@userName","lin'qin")); SqlParameter spm = new SqlParameter("@userName", "lin'qin"); cmd.Parameters.Add(spm);//添加單個(gè)參數(shù) //cmd.Parameters.Add("@userName", "lin'qin");//直接這種方式?jīng)]有錯(cuò)褂删,但是已經(jīng)過(guò)時(shí)了飞醉,棄用了 //cmd.Parameters.AddWithValue("@userName", "lin'qin");//單個(gè)參數(shù)的添加,推薦用這種方法 //SqlParameter pra = cmd.Parameters.Add("@userName",SqlDbType.VarChar,20); //pra.Value = "lin'qin"; //添加多個(gè)參數(shù)時(shí)使用數(shù)組 //SqlParameter[] paras = // { // new SqlParameter("userName", "lin'qin") //}; //cmd.Parameters.AddRange(paras); conn.Open(); Object o = cmd.ExecuteScalar(); conn.Close(); Console.WriteLine(o.ToString()); } Console.ReadKey(); }
-
參數(shù)使用的幾種方法
cmd.Parameter.Add();
添加單個(gè)參數(shù)
cmd.Parameters.Add("@userName", "lin'qin");//直接這種方式?jīng)]有錯(cuò)屯阀,但是已經(jīng)過(guò)時(shí)了缅帘,棄用了cmd.Parameter.AddWithValue();
cmd.Parameters.AddWithValue("@userName", "lin'qin");//單個(gè)參數(shù)的添加,推薦用這種方法cmd.Parameter.AddRange();
//添加多個(gè)參數(shù)時(shí)使用數(shù)組
//SqlParameter[] paras =
// {
// new SqlParameter("userName", "lin'qin")
//};
//cmd.Parameters.AddRange(paras);
-
參數(shù)的使用
//這個(gè)Direction就代表著說(shuō)這個(gè)參數(shù)是輸入?yún)?shù)還是輸出參數(shù)還是雙向參數(shù)還是返回值參數(shù)
spm.Direction = ParameterDirection.Input;//默認(rèn)就是input參數(shù)难衰。
- 輸入?yún)?shù)
參數(shù)化SQL語(yǔ)句或存儲(chǔ)過(guò)程 - 輸出參數(shù)
在存儲(chǔ)過(guò)程中以output標(biāo)識(shí)钦无,程序中是可以接受到存儲(chǔ)過(guò)程中需要返回的值,而不用return的
在代碼中Direction:Output
string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connStr))
{
SqlCommand cmd = new SqlCommand("GetName1", conn);
//調(diào)用存儲(chǔ)過(guò)程的方法
cmd.CommandType = CommandType.StoredProcedure;
//參數(shù)化sql語(yǔ)句中使用的是輸入?yún)?shù)
SqlParameter paraId = new SqlParameter("@Id",2);
cmd.Parameters.Add(paraId);//添加單個(gè)參數(shù)
//輸出參數(shù)
SqlParameter paraName = new SqlParameter("@Name",SqlDbType.NVarChar,10);
paraName.Direction = ParameterDirection.Output;
cmd.Parameters.Add(paraName);//添加單個(gè)參數(shù)
//這里遵循一個(gè)原則盖袭,最遲打開(kāi)失暂,最早關(guān)閉
//要使用連接時(shí)才打開(kāi)彼宠,使用完就關(guān)閉
conn.Open();
cmd.ExecuteScalar();
conn.Close();
Console.WriteLine(paraName.Value.ToString());
}
Console.ReadKey();
}
- 輸入輸出參數(shù)
在存儲(chǔ)過(guò)程中也是用output標(biāo)識(shí) 他需要傳入值,也輸出值弟塞,不用return
在代碼中Direction:InoutOutput凭峡,除了Direction的標(biāo)識(shí)不同外,還有需要插入Value值
string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
//輸入輸出參數(shù)--雙向參數(shù)
using (SqlConnection conn = new SqlConnection(connStr))
{
SqlCommand cmd = new SqlCommand("GetName2", conn);
//調(diào)用存儲(chǔ)過(guò)程的方法
cmd.CommandType = CommandType.StoredProcedure;
//輸入輸出參數(shù)决记,既傳入值也輸出值
SqlParameter paraName = new SqlParameter("@Name",SqlDbType.NVarChar,10);
paraName.Value = "里";
paraName.Direction = ParameterDirection.InputOutput;
cmd.Parameters.Add(paraName);//添加單個(gè)參數(shù)
//這里遵循一個(gè)原則摧冀,最遲打開(kāi),最早關(guān)閉
//要使用連接時(shí)才打開(kāi)系宫,使用完就關(guān)閉
conn.Open();
cmd.ExecuteScalar();
conn.Close();
Console.WriteLine(paraName.Value.ToString());
}
Console.ReadKey();
- 返回值參數(shù)
- 只可以返回的int類型的索昂,其他的類型會(huì)報(bào)錯(cuò),return進(jìn)行返回
- 返回字符串類型是不可以的扩借,如果要返回一個(gè)字符串類型楼镐,存儲(chǔ)過(guò)程會(huì)強(qiáng)制轉(zhuǎn)換成一個(gè)int類型,如果轉(zhuǎn)換不了往枷,就會(huì)報(bào)錯(cuò)
-
SqlDataReader
定義:提供一種從sqlserver數(shù)據(jù)庫(kù)讀取只進(jìn)的行流的方式
特點(diǎn):快速的框产、輕量級(jí)的、只讀的错洁、遍歷訪問(wèn)每一行數(shù)據(jù)的數(shù)據(jù)流秉宿、向一個(gè)方向,一行一行的讀取屯碴,不能向后讀取描睦,讀取功能弱但是讀取速度快,不能修改數(shù)據(jù)
缺點(diǎn): 不靈活导而,只適合數(shù)據(jù)量小的情況忱叭,只限于讀取數(shù)據(jù),一直占著連接
讀取方式:Read();獲取到第一行數(shù)據(jù)今艺,指針指向第二行的數(shù)據(jù)韵丑。要讀下一行的數(shù)據(jù)時(shí),再次調(diào)用Read()方法虚缎,獲取第二行的數(shù)據(jù)撵彻;當(dāng)調(diào)用Read()方法返回false時(shí),就表示不再有數(shù)據(jù)行实牡。
注意:連接對(duì)象要一直保持open()狀態(tài)陌僵,如果連接關(guān)閉,是不能讀取數(shù)據(jù)的创坞。
使用完成后碗短,應(yīng)該馬上調(diào)用Close()方法關(guān)閉,不然Reader()對(duì)象是會(huì)一直占著連接的-
創(chuàng)建方式:
- 是不能直接構(gòu)造的题涨,cmd.ExcuteReader()來(lái)創(chuàng)建偎谁。cmd.ExcuteReader(CommandBehavior. CloseConnection)傳入的這個(gè)值总滩,傳入的這個(gè)值的DataReader的好處是:關(guān)閉Reader對(duì)象是就會(huì)自動(dòng)關(guān)閉數(shù)據(jù)庫(kù)連接
- 讀取時(shí)盡量使用與數(shù)據(jù)庫(kù)字段類型相匹配的方法來(lái)取得對(duì)應(yīng)的值,會(huì)減少因類型不一致而增加類型轉(zhuǎn)換操作的性能損耗搭盾。
- 沒(méi)有讀取到末尾時(shí)就要關(guān)閉reader對(duì)象時(shí)咳秉,先調(diào)用cmd.Cancel(),然后再調(diào)用reader.Close();
- cmd.ExcuteReader()來(lái)獲取存儲(chǔ)過(guò)程的返回值或者輸出參數(shù),先調(diào)用reader.Close(),然后才能獲取到參數(shù)的值
-
常用屬性:
- Connection:獲取與我們Reader對(duì)象相關(guān)的SqlConnection
- FiedCount:可以當(dāng)前行中的列數(shù)
- HasRows:reader對(duì)象是否包含一行或者多行
- IsClosed:reader對(duì)象是否已關(guān)閉鸯隅,關(guān)閉:true澜建,打開(kāi):false
- Item[int]:列序號(hào),給定列序號(hào)的情況下蝌以,獲取指定列的值
- Item[String]:列名炕舵。獲取指定列的值
-
SqlDataReader讀取數(shù)據(jù)
-
常用方法
- close()方法 關(guān)閉dataReader數(shù)據(jù)閱讀器對(duì)象的
- GetInt32(列序號(hào)i)--根據(jù)數(shù)據(jù)類型相匹配的方法
- GetFiedType(列序號(hào)i)--獲取數(shù)據(jù)類型的type對(duì)象
- GetName(列序號(hào)i) -- 獲取指定列的列名
- GetOrdinal(列名) -- 獲取指定列的列序號(hào)
- Read() -- 使datareader對(duì)象前進(jìn)到下一條記錄
- NextResult() -- (如果dr讀取的是多結(jié)果集的數(shù)據(jù))使dr前進(jìn)到下一個(gè)結(jié)果
-
讀取
- Read():數(shù)據(jù)量小的情況,高效的
-
-
DataTable詳解
概念:DataSet (數(shù)據(jù)在內(nèi)存中的一個(gè)緩存跟畅,理解成內(nèi)存中的數(shù)據(jù)庫(kù)):是Ado.Net核心組件咽筋;DataTable是DataSet的重要成員(DataTable內(nèi)存中的一個(gè)表,可以理解成DataSet數(shù)據(jù)庫(kù)中的表):DataSet和DataTable就類似于數(shù)據(jù)庫(kù)與數(shù)據(jù)庫(kù)中的表一樣
-
應(yīng)用:一般是作為DataSet的成員使用徊件,它也可以獨(dú)立創(chuàng)建與使用奸攻,結(jié)合DataAdapter適配器使用。
-
架構(gòu):DataTable(類似于數(shù)據(jù)庫(kù)中的表虱痕,他的架構(gòu)也就是結(jié)構(gòu))睹耐,列+約束來(lái)表示
- DataColumn 列對(duì)象,定義好后要添加到DataTable里面
-
成員:行 DataRow
-
構(gòu)造:
- 無(wú)參構(gòu)造:DataTable() DataTable(表名)
-
常用屬性:
- columns 列集合部翘;Rows 行集合硝训;Contrains 約束的集合;DataSet :DataTable所屬的DataSet
PrimaryKey:主鍵(列的數(shù)組) TableName(指定一個(gè)表名)
- columns 列集合部翘;Rows 行集合硝训;Contrains 約束的集合;DataSet :DataTable所屬的DataSet
-
方法
- AcceptChanges() 對(duì)DataTable所做的更改的提交
- RejectChanges() 回滾新思,取消更改
- Clear() 清空數(shù)據(jù)
- Copy() 復(fù)制架構(gòu)和數(shù)據(jù)
- Clone() 只復(fù)制架構(gòu)窖梁,不包含數(shù)據(jù)
- Load(IDataReader) 通過(guò)提供的IDataReader,用某個(gè)數(shù)據(jù)源的值來(lái)填充DataTable
- Merge(DataTable)/Merge() 合并夹囚,將指定的DataTable合并到當(dāng)前的DataTable中來(lái) 纵刘,前提是是結(jié)構(gòu)相同的情況,結(jié)構(gòu)不同的話需要特別的處理
- NewRow() 創(chuàng)建一個(gè)DataRow崔兴,與DataTable具有相同的架構(gòu)
- Reset() 將DataTable重置到最初始的狀態(tài)
- Select() 獲取到DataTable所有的行的數(shù)組彰导,返回的是一個(gè)數(shù)組,參數(shù)可以帶篩選條件(可以排序)
DataRow[] row = dt1.Select();//獲取所有行
DataRow[] row1 = dt1.Select("Id>1""Id desc");//條件篩選敲茄,排序
-
DataSet詳解
-
概念:DataSet是數(shù)據(jù)在內(nèi)存中的緩存,可以理解成內(nèi)存中的數(shù)據(jù)庫(kù)山析,DataTable內(nèi)存數(shù)據(jù)庫(kù)中的一個(gè)表堰燎,是Ado.net中的核心組件,數(shù)據(jù)庫(kù)中的數(shù)據(jù)加載到內(nèi)存中
-
成員:一組DataTable組成笋轨,DataRelation(表與表之間的關(guān)系)和DataTable是相互關(guān)聯(lián)的秆剪,他們一起實(shí)施的數(shù)據(jù)的完整性
-
應(yīng)用 :三種
- 1.結(jié)合DataAdapter使用赊淑,DataAdapter將數(shù)據(jù)填充到我們的DataSet中
- 2.DataAdapter將DataSet中的更改提交到數(shù)據(jù)庫(kù),是數(shù)據(jù)庫(kù)中的數(shù)據(jù)和我們的更改保持一致
- 3.將XML文檔或文本加載到DataSet中去
-
作用:DataSet將數(shù)據(jù)加載到內(nèi)存中執(zhí)行的仅讽,是內(nèi)存中的緩存陶缺。
- 1.提高了數(shù)據(jù)訪問(wèn)的速度
- 2.提高了硬盤數(shù)據(jù)的安全性,因?yàn)镈ataTable的數(shù)據(jù)都是在內(nèi)存中洁灵,沒(méi)有提交到數(shù)據(jù)庫(kù)饱岸,就算不正確是錯(cuò)誤的也不會(huì)影響到數(shù)據(jù)庫(kù)
- 3.因?yàn)榍皟牲c(diǎn),也影響了程序運(yùn)行的速度和穩(wěn)定性
-
特性:獨(dú)立性徽千,不依賴與任何數(shù)據(jù)庫(kù)苫费,因?yàn)槭羌虞d在內(nèi)存中,所以無(wú)論是什么數(shù)據(jù)源双抽,都可以斷開(kāi)與數(shù)據(jù)庫(kù)的連接百框,可以獨(dú)立存在進(jìn)行處理,可以離線和連接牍汹。DataSet里面的數(shù)據(jù)時(shí)通過(guò)Xml來(lái)描述的铐维,所以是可以用xml來(lái)表示的數(shù)據(jù)視圖,數(shù)據(jù)操作靈活性強(qiáng)
-
創(chuàng)建:DataSet() 無(wú)參構(gòu)造 DataSet(名稱) 帶參數(shù)的構(gòu)造
-
常用屬性:
-
方法:
-
-
約束與關(guān)系
- 創(chuàng)建約束:
dt1.PrimaryKey = new DataColumn[]
{
dt1.Columns[0]
};//主鍵 ---自動(dòng)創(chuàng)建一個(gè)主鍵約束
dt2.Constraints.Add(new UniqueConstraint("uc", dt2.Columns[1]));//添加一個(gè)唯一約束
//外鍵約束,第一個(gè)是父列慎菲,然后是子列
dt1.Constraints.Add(new ForeignKeyConstraint("fk",dt2.Columns[0], dt1.Columns[3]));
//默認(rèn)情況:建立關(guān)系,就自動(dòng)在父表中建立唯一約束嫁蛇,子表中外鍵列建立一個(gè)外鍵約束
DataRelation relation = new DataRelation("relation",dt2.Columns[0],dt1.Columns[3],true);//這樣就會(huì)自動(dòng)創(chuàng)建上面的約束,最后一個(gè)屬性如果設(shè)置成false,就只會(huì)建立聯(lián)系钧嘶,而不會(huì)創(chuàng)建以上兩種約束
//添加到ds中
ds.Relations.Add(relation);//添加到relations中
- 創(chuàng)建關(guān)系:
- 使用:
//使用關(guān)系
foreach (DataRow dr in dt2.Rows)//首先遍歷父表中的所有行
{
DataRow[] rows = dr.GetChildRows(relation);//通過(guò)dr.GetChildRows(relation)來(lái)獲取子表有多少行
foreach (DataRow r in rows)
{
Console.WriteLine($"UserId:{r[0].ToString()},UserName:{r[1].ToString()}棠众,Age:{r[2].ToString()},DeptId:{r[3].ToString()}");
}
}
//通過(guò)父表讀取子表中的數(shù)據(jù)
DataRow[] rows = dt2.Rows[0].GetChildRows(relation);
foreach (DataRow r in rows)
{
Console.WriteLine($"UserId:{r[0].ToString()},UserName:{r[1].ToString()},Age:{r[2].ToString()},DeptId:{r[3].ToString()}");
}
//可以通過(guò)子表來(lái)讀取父表中的數(shù)據(jù)嗎
DataRow rows = dt1.Rows[0].GetParentRow(relation);
Console.WriteLine($"DeptId:{rows[0].ToString()},DeptName:{rows[1].ToString()}");
-
SqlDataAdapter
-
SqlDataAdapter是什么
- 數(shù)據(jù)適配器(橋接器)有决,DataSet與數(shù)據(jù)之間用于檢索和保存數(shù)據(jù)的橋梁闸拿。
- SqlDataAdapter類 填充DataSet以及更新數(shù)據(jù)源(也就是各種不同的數(shù)據(jù)庫(kù))的一組數(shù)據(jù)庫(kù)執(zhí)行命令和一個(gè)數(shù)據(jù)庫(kù)連接。
- SqlDataAdapter是我們DataSet和SQLServer之間的橋接器
-
它是如何提供橋接的
- Fill();這個(gè)方法就可以將我們的sql命令檢索到的數(shù)據(jù)填充到DataSet里邊
- Update(); 將更改提交到數(shù)據(jù)庫(kù)书幕,讓數(shù)據(jù)庫(kù)中的數(shù)據(jù)和DataSet中的數(shù)據(jù)保持一致
- 和SqlConnection和SqlCommand一起使用可以提高訪問(wèn)數(shù)據(jù)的速度
-
4個(gè)重要屬性
- SelectCommand新荤,查詢; 這個(gè)屬性生成一個(gè)對(duì)象SqlCommand
- InsertCommand台汇,插入一條記錄
- UpdateCommand苛骨,更新數(shù)據(jù)庫(kù)中的記錄
- DeleteCommand,刪除數(shù)據(jù)庫(kù)中的記錄
- 從上面可知苟呐,SqlDataAdapter也是建立在SqlCommand基礎(chǔ)之上的
-
4種創(chuàng)建方式
-
string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
string sql = "select * from UserInfo";
SqlConnection conn = new SqlConnection(connStr);
//1.單獨(dú)設(shè)置SelectCommand
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = new SqlCommand(sql,conn);
//2.通過(guò)我們的SqlCommand對(duì)象來(lái)實(shí)例化一個(gè)adapter
SqlCommand cmd = new SqlCommand(sql,conn);
SqlDataAdapter adapter1 = new SqlDataAdapter(cmd);
//3.查詢語(yǔ)句和連接對(duì)象來(lái)實(shí)例化一個(gè)adapter
SqlDataAdapter adapter2 = new SqlDataAdapter(sql,conn);
//4.查詢語(yǔ)句和連接字符串痒芝,也可以構(gòu)建一個(gè)adapter?,很少用
SqlDataAdapter adapter3 = new SqlDataAdapter(sql, connStr);
//如果執(zhí)行的是T-SQL查詢語(yǔ)句牵素,不帶參數(shù)的情況下严衬,選擇第三種方式
//帶參數(shù),添加參數(shù)笆呆,SqlCommand请琳,選擇第二種或者第一種
//不推薦使用第四種
Console.ReadKey();
-
DataAdapter填充DataSet和DataTable
Fill();填充到ds或dt中
-
連接與斷開(kāi)兩種方式填充數(shù)據(jù)的執(zhí)行機(jī)制
Fill(); 斷開(kāi)式粱挡;沒(méi)有顯示打開(kāi)conn對(duì)象---由DataAdapter來(lái)做這件事--獲取數(shù)據(jù)--填充到ds\dt中--自動(dòng)關(guān)閉conn;斷開(kāi)式給我們的錯(cuò)覺(jué)是:斷開(kāi)的俄精,沒(méi)有與數(shù)據(jù)庫(kù)連接 询筏,其實(shí)只是這個(gè)過(guò)程都是由da來(lái)完成
連接式,顯示打開(kāi)conn竖慧,顯示打開(kāi)和關(guān)閉conn時(shí)嫌套,F(xiàn)ill()前后conn狀態(tài)都是open
區(qū)別:速度上,連接式速度比斷開(kāi)式快(只是在填充數(shù)據(jù)上测蘑,因?yàn)榇蜷_(kāi)式不用做打開(kāi)連接關(guān)閉連接的過(guò)程)
盡量選擇連接式灌危,因?yàn)樾矢摺R淮涡约虞d到內(nèi)存中碳胳,加載到內(nèi)存后就可以斷開(kāi)conn連接
-
Adapter更新數(shù)據(jù)庫(kù)
-
更新方式:Update(ds/dt/Rows)勇蝙; 放數(shù)據(jù)的是DataRow對(duì)象
- RowState:Added:執(zhí)行插入; - RowState:Modified:執(zhí)行修改挨约; - RowState:Deleted:執(zhí)行刪除味混; 更新時(shí),Modified--已修改的--da.UpdateCommand; Added -- 已添加 ---da.InsertCommand; Deleted -- 已刪除 -- da.DeleteCommand;
-
配置對(duì)應(yīng)的命令屬性的方式
- SqlCommandBuilder:自動(dòng)為DataAdapter配置相關(guān)的命令
根據(jù)行狀態(tài)自動(dòng)配置相應(yīng)的Command命令,通過(guò)Adapter對(duì)象來(lái)進(jìn)行實(shí)例化 SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(da);
- 手動(dòng)配置SqlCommand:
//為da手動(dòng)配置命令 SqlCommand insertCmd = new SqlCommand("insert into UserInfo (UserName,Age,DeptId) values (@UserName,@Age,@DeptId)", conn); SqlParameter[] paras = { new SqlParameter("UserName",SqlDbType.VarChar,10,"UserName"), new SqlParameter("Age",SqlDbType.Int,4,"Age"), new SqlParameter("DeptId",SqlDbType.Int,4,"DeptId") }; insertCmd.Parameters.Clear(); insertCmd.Parameters.AddRange(paras); da.InsertCommand = insertCmd;
-
-
Adapter和Reader的比較
相同:都是執(zhí)行查詢诫惭,將數(shù)據(jù)讀取出來(lái)翁锡,一個(gè)或多個(gè)
- SqlDataReader :提供一種從數(shù)據(jù)庫(kù)中讀取數(shù)據(jù)的流的方式
- SqlDataAdapter:是數(shù)據(jù)庫(kù)與DataSet之間的一個(gè)橋接器,通過(guò)Fill();方法填充到DataSet中夕土,通過(guò)Update()馆衔;方法更新到數(shù)據(jù)庫(kù)-
性能對(duì)比:速度、占用內(nèi)存怨绣、連接狀態(tài)角溃、適用數(shù)據(jù)量、讀取方式篮撑、是否可讀等方面進(jìn)行對(duì)比
速度:DataReader讀取速度比較快减细,DataAdapter讀取速度比較慢;(數(shù)據(jù)量小的情況下赢笨,速度快慢不明顯)
數(shù)據(jù)量:DataReader適用于數(shù)據(jù)量形打颉;DataAdapter是用于數(shù)據(jù)量大
占用內(nèi)存:DataReader一次性只加載一條數(shù)據(jù)茧妒,一條一條的讀取萧吠,占用內(nèi)存小桐筏;DataAdapter是一次性加載怎憋,占用內(nèi)存比較大
連接:DataReader,一直占用連接九昧;DataAdapter一次性讀取到內(nèi)存中(支持?jǐn)嚅_(kāi)與連接兩種方式)
讀取方式:DataReader绊袋,從頭讀到尾,一條一條的讀铸鹰,讀一條丟一條癌别,只能向前不能后退(即時(shí)存儲(chǔ)),功能弱蹋笼,不靈活展姐,只讀的不可修改; DataAdapter剖毯,一次性加載到內(nèi)存中(將一個(gè)或多個(gè))圾笨,可以任意讀取,靈活逊谋,可讀可寫擂达;
不要求隨意讀取钻趋、不修改弯蚜、數(shù)據(jù)量小的情況下室囊,選用SqlDataReader --速度快柿赊,占用內(nèi)存小
可以隨意讀取控轿,可以修改承桥,數(shù)據(jù)量大的情況下漆魔,選擇SqlDataAdapter --靈活性硝全,占用內(nèi)存大部宿,但是不會(huì)一直占用連接
-
Ado.Net調(diào)用數(shù)據(jù)庫(kù)事務(wù)
-
回顧事務(wù)知識(shí):一組操作--一個(gè)操作來(lái)執(zhí)行抄腔,是一致性提交的,否則則回滾回最初的狀態(tài)理张。結(jié)果:成功or失敗赫蛇,事務(wù)的特征:原子性,一致性涯穷,獨(dú)立性棍掐,永久性
-
事務(wù)執(zhí)行過(guò)程:
- 開(kāi)啟事務(wù),成功-提交 拷况,失敗-回滾作煌;
- 例如:插入操作時(shí),發(fā)生故障赚瘦,并未提交到數(shù)據(jù)庫(kù)粟誓,可以維護(hù)數(shù)據(jù)的完整性
//數(shù)據(jù)庫(kù)存儲(chǔ)過(guò)程 -- 事務(wù):一致性提交,回滾 --程序如何來(lái)調(diào)用事務(wù)?事務(wù)放在存儲(chǔ)過(guò)程里 ALTER PROC [dbo].[AddUserByTran] @UserName VARCHAR(10), @Age INT, @DeptName VARCHAR(10) AS BEGIN begin TRAN begin TRY -- 插入部門信息 INSERT INTO DeptInfo(DeptName) VALUES (@DeptName); DECLARE @deptId INT SELECT @deptId = @@IDENTITY; -- 插入用戶信息 INSERT INTO dbo.UserInfo ( UserName, Age, DeptId ) VALUES ( @UserName,@Age,@deptId) COMMIT TRAN--提交 RETURN 1; end TRY begin CATCH ROLLBACK RETURN 0; END CATCH END //c#代碼執(zhí)行數(shù)據(jù)庫(kù)中的存儲(chǔ)過(guò)程 string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString; using (SqlConnection conn = new SqlConnection(connStr)) { //調(diào)用存儲(chǔ)過(guò)程 SqlCommand cmd = new SqlCommand("AddUserByTran", conn); cmd.CommandType = CommandType.StoredProcedure;//調(diào)用存儲(chǔ)過(guò)程必要的 cmd.Parameters.Clear(); SqlParameter[] paras ={ new SqlParameter("@UserName","lily"), new SqlParameter("@Age",26), new SqlParameter("@DeptName","銷售部"), new SqlParameter ("@reValue",SqlDbType.Int,4) }; paras[3].Direction = ParameterDirection.ReturnValue;//返回值參數(shù) cmd.Parameters.AddRange(paras); //執(zhí)行 conn.Open(); cmd.ExecuteNonQuery(); int state = int.Parse(paras[3].Value.ToString()); conn.Close(); if (state == 1) { Console.WriteLine("用戶信息添加成功!"); } else { Console.WriteLine("用戶信息添加失敗"); } }
-
Ado.Net如何調(diào)用事務(wù) --實(shí)質(zhì):調(diào)用一個(gè)普通的存儲(chǔ)過(guò)程---里面的邏輯是一段事務(wù)代碼
- 批量導(dǎo)入 --- 如果使用數(shù)據(jù)庫(kù)事務(wù)起意,要傳入一千組參數(shù)的情況鹰服,太復(fù)雜--- 這種方法不具有可行性
-
-
Ado.Net.SqlTransaction 開(kāi)啟事務(wù)---循環(huán)--- 操作定義,傳入不同的參數(shù)值
SqlTransaction 介紹:SQLServer數(shù)據(jù)庫(kù)中執(zhí)行T-SQL事務(wù)
-
與數(shù)據(jù)庫(kù)事務(wù)有何不同?
string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString; using (SqlConnection conn = new SqlConnection(connStr)) { SqlTransaction tran = null; try { //先決條件:連接打開(kāi) conn.Open(); //IsolationLevel.ReadCommitted,可以設(shè)置隔離級(jí)別悲酷,ReadCommitted是默認(rèn)的隔離級(jí)別 tran = conn.BeginTransaction();//開(kāi)啟一個(gè)事務(wù) SqlCommand cmd = conn.CreateCommand(); cmd.Transaction = tran;//設(shè)置在Command中要執(zhí)行的事務(wù) //定義要執(zhí)行的操作 cmd.CommandText = "insert into DeptInfo (DeptName) values (@DeptName);select @@identity"; cmd.Parameters.Add(new SqlParameter("@DeptName", "采購(gòu)部")); Object oId = cmd.ExecuteScalar(); cmd.Parameters.Clear(); int DeptId = 0; if (oId != null) { DeptId = int.Parse(oId.ToString()); } cmd.CommandText = "INSERT INTO dbo.UserInfo(UserName, Age, DeptId) VALUES (@UserName, @Age, @DeptId)"; SqlParameter[] paras = { new SqlParameter ("@UserName","luhan"), new SqlParameter ("@Age",29), new SqlParameter ("@DeptId",DeptId) }; cmd.Parameters.AddRange(paras); cmd.ExecuteNonQuery(); cmd.Parameters.Clear(); //下一步操作 tran.Commit();//提交事務(wù) Console.WriteLine("用戶提交成功"); } catch(SqlException ex) { tran.Rollback();//出異程撞耍回滾 } finally { tran.Dispose(); conn.Close(); } } Console.ReadKey();
SqlTransaction 的使用 :開(kāi)啟事務(wù),執(zhí)行一組操作设易,更靈活逗柴,不管是不是批量,他都可以駕馭
-
-
封裝的數(shù)據(jù)訪問(wèn)通用類DbHelp
-
為什么封裝這個(gè)類
- 只要與數(shù)據(jù)庫(kù)發(fā)生數(shù)據(jù)交互:增 刪 改 查 --- 都要與數(shù)據(jù)庫(kù)通信顿肺,做一些相同的事 --- 建立連接戏溺,T-SQL命令,執(zhí)行命令的對(duì)象Command屠尊,選擇執(zhí)行方式旷祸,得到相應(yīng)的結(jié)果,關(guān)閉連接
- 如果把整個(gè)過(guò)程寫在一起讼昆,整個(gè)代碼就會(huì)顯得雜亂無(wú)章托享,不清晰
- 做一些改善 -- 把一些相同的邏輯寫在一起封裝起來(lái),達(dá)到通用的目的
- 產(chǎn)生什么作用 -- 代碼重利用控淡,提高開(kāi)發(fā)效率嫌吠,不再考慮交互過(guò)程,邏輯很清晰掺炭。不管項(xiàng)目架構(gòu)是否是分層的辫诅,都很重要。
-
DbHelp類的內(nèi)容規(guī)劃
- 1.連接鑰匙:-- 連接字符串 -- 寫在配置文件里 -- 建立連接 -- 連接釋放 -- using()語(yǔ)句塊(如果忘了釋放涧狮,using語(yǔ)句塊會(huì)幫我們進(jìn)行釋放)
- 2.SqlCommand三種執(zhí)行方法炕矮,ExcuteNonQuery(); 這個(gè)方法就是針對(duì)增刪改的操作;ExcuteScalar(); 這個(gè)方法針對(duì)查詢者冤,返回一個(gè)值肤视; ExcuteReader(); 這個(gè)方法是執(zhí)行一個(gè)T-SQL命令,生成一個(gè)數(shù)據(jù)流(SqlDataReader()) ,這種方法讀取起來(lái)比較快速涉枫,適用于只是讀取數(shù)據(jù)邢滑,不需要進(jìn)行二次加工的數(shù)據(jù)。
- 3.SqlDataAdapter填充DataSet(針對(duì)一個(gè)或多個(gè)結(jié)果集)或DataTable(針對(duì)單個(gè)結(jié)果集)
- 4.SqlTransation(執(zhí)行事務(wù)的方法):每一個(gè)操作定義成一個(gè)對(duì)象CommandInfo愿汰,每一個(gè)操作執(zhí)行一個(gè)T-SQL命令困后,傳入?yún)?shù)(參數(shù)數(shù)組),CommandType(執(zhí)行的參數(shù)類型)
-
具體的實(shí)現(xiàn)過(guò)程
-
SqlCommand三種執(zhí)行方法:conn是open狀態(tài)
- ExcuteNorQuery(); 執(zhí)行T-SQL,返回受影響的行數(shù)衬廷,是一個(gè)int類型摇予,執(zhí)行的可能是T-SQL語(yǔ)句或者存儲(chǔ)過(guò)程,所以要考慮CommandType
/// <summary> /// 執(zhí)行T-SQL吗跋,返回受影響的行數(shù) Insert侧戴,Update宁昭,Delete /// </summary> /// <param name="sql">sql語(yǔ)句或存儲(chǔ)過(guò)程名</param> /// <param name="CommandType">類型</param>或傳入一個(gè)int cmdType,1代表sql語(yǔ)句酗宋,2代表存儲(chǔ)過(guò)程 /// <param name="">參數(shù)列表积仗,分兩種,傳值或不傳值的情況</param> /// <returns></returns> public static int ExcuteNonQuery(string sql,int cmdType,params SqlParameter[] paras) { int count = 0; using (SqlConnection conn = new SqlConnection(connStr)) { SqlCommand cmd = new SqlCommand(sql, conn); if (cmdType == 2) cmd.CommandType = CommandType.StoredProcedure; if(paras!=null && paras.Length>0) cmd.Parameters.AddRange(paras); conn.Open(); count = cmd.ExecuteNonQuery(); conn.Close(); } return count; }
- ExcuteScalar(); 執(zhí)行查詢本缠,返回查詢結(jié)果集第一行第一列的值object斥扛,忽略其他行或列
public static object ExcuteScalar(string sql, int cmdType, params SqlParameter[] paras) { object o = null; using (SqlConnection conn = new SqlConnection(connStr)) { SqlCommand cmd = new SqlCommand(sql, conn); if (cmdType == 2) cmd.CommandType = CommandType.StoredProcedure; if (paras != null && paras.Length > 0) cmd.Parameters.AddRange(paras); conn.Open(); o = cmd.ExecuteScalar(); conn.Close(); } return o; }
- ExcuteReader(); 執(zhí)行查詢,生成SqlDataReader丹锹,可以對(duì)結(jié)果集的數(shù)據(jù)進(jìn)行一行一行的即時(shí)讀取
/// <summary> /// 執(zhí)行查詢,生成SqlDataReader芬失,可以對(duì)結(jié)果集的數(shù)據(jù)進(jìn)行一行一行的即時(shí)讀取 /// </summary> /// <param name="sql"></param> /// <param name="cmdType"></param> /// <param name="paras"></param> /// <returns></returns> public static SqlDataReader ExcuteReader(string sql, int cmdType, params SqlParameter[] paras) { SqlDataReader dr = null; SqlConnection conn = new SqlConnection(connStr); SqlCommand cmd = new SqlCommand(sql, conn); if (cmdType == 2) cmd.CommandType = CommandType.StoredProcedure; if (paras != null && paras.Length > 0) cmd.Parameters.AddRange(paras); try { conn.Open(); //CommandBehavior.CloseConnection,作用是釋放Reader()楣黍,可以一起釋放連接 dr = cmd.ExecuteReader(CommandBehavior.CloseConnection); } catch(SqlException ex) { conn.Close(); //把這里的異常包裹成新的異常往上拋 throw new Exception("執(zhí)行查詢異常", ex); } return dr; }
- ExcuteNorQuery(); 執(zhí)行T-SQL,返回受影響的行數(shù)衬廷,是一個(gè)int類型摇予,執(zhí)行的可能是T-SQL語(yǔ)句或者存儲(chǔ)過(guò)程,所以要考慮CommandType
-
-
-
封裝DbHelper
class DbHelper
{
//連接字符串
private static readonly string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
SqlConnection conn = null;
//private SqlConnection GetConn()
//{
// conn = new SqlConnection(connStr);
// return conn;
//}
/// <summary>
/// 執(zhí)行T-SQL,返回受影響的行數(shù) Insert棱烂,Update租漂,Delete
/// </summary>
/// <param name="sql">sql語(yǔ)句或存儲(chǔ)過(guò)程名</param>
/// <param name="CommandType">類型</param>或傳入一個(gè)int cmdType,1代表sql語(yǔ)句颊糜,2代表存儲(chǔ)過(guò)程
/// <param name="">參數(shù)列表哩治,分兩種,傳值或不傳值的情況</param>
/// <returns></returns>
public static int ExcuteNonQuery(string sql,int cmdType,params SqlParameter[] paras)
{
int count = 0;
using (SqlConnection conn = new SqlConnection(connStr))
{
//SqlCommand cmd = new SqlCommand(sql, conn);
//if (cmdType == 2)
// cmd.CommandType = CommandType.StoredProcedure;
//if(paras!=null && paras.Length>0)
//cmd.Parameters.AddRange(paras);
//conn.Open();
SqlCommand cmd = BuildCommand(conn, sql, cmdType, null, paras);
count = cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
conn.Close();
}
return count;
}
public static object ExcuteScalar(string sql, int cmdType, params SqlParameter[] paras)
{
object o = null;
using (SqlConnection conn = new SqlConnection(connStr))
{
//SqlCommand cmd = new SqlCommand(sql, conn);
//if (cmdType == 2)
// cmd.CommandType = CommandType.StoredProcedure;
//if (paras != null && paras.Length > 0)
// cmd.Parameters.AddRange(paras);
//conn.Open();
SqlCommand cmd = BuildCommand(conn, sql, cmdType, null, paras);
o = cmd.ExecuteScalar();
cmd.Parameters.Clear();
conn.Close();
}
return o;
}
/// <summary>
/// 執(zhí)行查詢衬鱼,生成SqlDataReader业筏,可以對(duì)結(jié)果集的數(shù)據(jù)進(jìn)行一行一行的即時(shí)讀取
/// </summary>
/// <param name="sql"></param>
/// <param name="cmdType"></param>
/// <param name="paras"></param>
/// <returns></returns>
public static SqlDataReader ExcuteReader(string sql, int cmdType, params SqlParameter[] paras)
{
SqlDataReader dr = null;
SqlConnection conn = new SqlConnection(connStr);
//SqlCommand cmd = new SqlCommand(sql, conn);
//if (cmdType == 2)
// cmd.CommandType = CommandType.StoredProcedure;
//if (paras != null && paras.Length > 0)
// cmd.Parameters.AddRange(paras);
SqlCommand cmd = BuildCommand(conn, sql, cmdType, null, paras);
try {
//conn.Open();
//CommandBehavior.CloseConnection,作用是釋放Reader(),可以一起釋放連接
dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
cmd.Parameters.Clear();
}
catch(SqlException ex)
{
conn.Close();
//把這里的異常包裹成新的異常往上拋
throw new Exception("執(zhí)行查詢異常", ex);
}
return dr;
}
/// <summary>
/// 填充DataSet鸟赫,對(duì)一個(gè)或多個(gè)結(jié)果集都有效
/// </summary>
/// <param name="sql"></param>
/// <param name="cmdType"></param>
/// <param name="paras"></param>
/// <returns></returns>
public static DataSet GetDataSet(string sql, int cmdType, params SqlParameter[] paras)
{
DataSet ds = new DataSet();
using (SqlConnection conn = new SqlConnection(connStr))
{
//SqlDataAdapter da = new SqlDataAdapter(sql, conn);這是不傳參的情況下蒜胖,如果要傳參數(shù),這種情況我們就要拋棄了
//SqlCommand cmd = new SqlCommand(sql,conn);
//if (cmdType == 2)
// cmd.CommandType = CommandType.StoredProcedure;
//if (paras != null && paras.Length > 0)
// cmd.Parameters.AddRange(paras);
SqlCommand cmd = BuildCommand(conn, sql, cmdType, null, paras);
SqlDataAdapter da = new SqlDataAdapter(cmd);
//conn.Open();
da.Fill(ds);
conn.Close();
}
return ds;
}
/// <summary>
/// 填充DataTable抛蚤,一個(gè)結(jié)果集台谢,只針對(duì)單個(gè)表
/// </summary>
/// <param name="sql"></param>
/// <param name="cmdType"></param>
/// <param name="paras"></param>
/// <returns></returns>
public static DataTable GetDataTable(string sql, int cmdType, params SqlParameter[] paras)
{
DataTable dt = new DataTable();
using (SqlConnection conn = new SqlConnection(connStr))
{
//SqlDataAdapter da = new SqlDataAdapter(sql, conn);這是不傳參的情況下,如果要傳參數(shù)岁经,這種情況我們就要拋棄了
//SqlCommand cmd = new SqlCommand(sql, conn);
//if (cmdType == 2)
// cmd.CommandType = CommandType.StoredProcedure;
//if (paras != null && paras.Length > 0)
// cmd.Parameters.AddRange(paras);
SqlCommand cmd = BuildCommand(conn, sql, cmdType, null, paras);
SqlDataAdapter da = new SqlDataAdapter(cmd);
//conn.Open();
da.Fill(dt);
conn.Close();
}
return dt;
}
/// <summary>
/// 事務(wù)朋沮,一系列的SQL語(yǔ)句 針對(duì)的是我們的增刪改,insert update delete
/// </summary>
/// <param name="listSQL"></param>
/// <returns></returns>
public static bool ExcuteTrans(List<string> listSQL)
{
//using語(yǔ)句塊是不存在異常處理機(jī)制的缀壤,只是相當(dāng)于try樊拓,finally;
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
//conn.BeginTransaction();開(kāi)啟事務(wù)诉位,要求conn必須是open才可以開(kāi)啟事務(wù)
SqlTransaction trans = conn.BeginTransaction();
//SqlCommand cmd = conn.CreateCommand();
////設(shè)置Command的Transaction為我們的Command開(kāi)啟事務(wù)
//cmd.Transaction = trans;
SqlCommand cmd = BuildCommand(conn, "", 1, trans);
try
{
for (int i = 0; i < listSQL.Count; i++)
{
cmd.CommandText = listSQL[i];
//事務(wù)里做的操作一般都是增刪改操作骑脱,所以直接調(diào)用ExecuteNonQuery();
cmd.ExecuteNonQuery();
}
trans.Commit();
return true;
}
catch(SqlException ex)
{
trans.Rollback();
throw new Exception("執(zhí)行出現(xiàn)異常");
}
finally
{
trans.Dispose();
cmd.Dispose();
conn.Close();
}
}
}
public static bool ExcuteTrans(List<CmdInfo> listCmd)
{
//using語(yǔ)句塊是不存在異常處理機(jī)制的,只是相當(dāng)于try苍糠,finally叁丧;
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
//conn.BeginTransaction();開(kāi)啟事務(wù),要求conn必須是open才可以開(kāi)啟事務(wù)
SqlTransaction trans = conn.BeginTransaction();
//SqlCommand cmd = conn.CreateCommand();
////設(shè)置Command的Transaction為我們的Command開(kāi)啟事務(wù)
//cmd.Transaction = trans;
SqlCommand cmd = BuildCommand(conn, "", 1, trans);
try
{
for (int i = 0; i < listCmd.Count; i++)
{
cmd.CommandText = listCmd[i].CommandText;
if (listCmd[i].CmdType == 2)
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Clear();
if(listCmd[i].Parameters!=null && listCmd[i].Parameters.Length >0)
cmd.Parameters.AddRange(listCmd[i].Parameters);
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();//很重要
}
trans.Commit();
return true;
}
catch (SqlException ex)
{
trans.Rollback();
throw new Exception("執(zhí)行出現(xiàn)異常");
}
finally
{
trans.Dispose();
cmd.Dispose();
conn.Close();
}
}
}
/// <summary>
/// 構(gòu)造SqlCommand
/// </summary>
/// <param name="conn"></param>
/// <param name="sql"></param>
/// <param name="cmdType"></param>
/// <param name="trans"></param>
/// <param name="paras"></param>
/// <returns></returns>
private static SqlCommand BuildCommand(SqlConnection conn,string sql,int cmdType,SqlTransaction trans,params SqlParameter[] paras)
{
SqlCommand cmd = new SqlCommand(sql, conn);
if (cmdType == 2)
cmd.CommandType = CommandType.StoredProcedure;
if (paras != null && paras.Length > 0)
cmd.Parameters.AddRange(paras);
if (conn.State == ConnectionState.Closed)
conn.Open();
if (trans != null)
cmd.Transaction = trans;
return cmd;
}
}