ADO.NET

  • 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.png
  • 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)建

image.png
  • 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è)表名)
    • 方法

      • 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;
                               }
        
  • 封裝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;
        }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市拥娄,隨后出現(xiàn)的幾起案子蚊锹,更是在濱河造成了極大的恐慌,老刑警劉巖稚瘾,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件牡昆,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡摊欠,警方通過(guò)查閱死者的電腦和手機(jī)丢烘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)些椒,“玉大人播瞳,你說(shuō)我怎么就攤上這事∶飧猓” “怎么了赢乓?”我有些...
    開(kāi)封第一講書人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)石窑。 經(jīng)常有香客問(wèn)我牌芋,道長(zhǎng),這世上最難降的妖魔是什么松逊? 我笑而不...
    開(kāi)封第一講書人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任躺屁,我火速辦了婚禮,結(jié)果婚禮上棺棵,老公的妹妹穿的比我還像新娘楼咳。我一直安慰自己,他們只是感情好烛恤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布母怜。 她就那樣靜靜地躺著,像睡著了一般缚柏。 火紅的嫁衣襯著肌膚如雪苹熏。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,462評(píng)論 1 302
  • 那天币喧,我揣著相機(jī)與錄音轨域,去河邊找鬼。 笑死杀餐,一個(gè)胖子當(dāng)著我的面吹牛干发,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播史翘,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼枉长,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼冀续!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起必峰,我...
    開(kāi)封第一講書人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤洪唐,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后吼蚁,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體凭需,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年肝匆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了粒蜈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡术唬,死狀恐怖薪伏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情粗仓,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布设捐,位于F島的核電站借浊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏萝招。R本人自食惡果不足惜蚂斤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望槐沼。 院中可真熱鬧曙蒸,春花似錦、人聲如沸岗钩。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)兼吓。三九已至臂港,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間视搏,已是汗流浹背审孽。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留浑娜,地道東北人佑力。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像筋遭,于是被迫代替她去往敵國(guó)和親打颤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子暴拄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容