ADO.Net知识总结
- SqlDataReader是連接相關(guān)的,SqlDataReader中的查詢結(jié)果并不是放到程序中的,而是放在數(shù)據(jù)庫服務(wù)器中,SqlDataReader只是相當(dāng)于一個(gè)指針(游標(biāo)), 只能讀取當(dāng)前游標(biāo)指向的行,一旦連接斷開再不能讀取.這樣做的好處是無論查詢結(jié)果有多少條,對程序占用的內(nèi)存幾乎沒有影響.
- SqlDataReader對于小數(shù)據(jù)量的數(shù)據(jù)來說帶來的只有麻煩. ADO.NET中提供了數(shù)據(jù)集的機(jī)制,將數(shù)據(jù)結(jié)果填充到本地內(nèi)存中,這樣連接斷開,服務(wù)器斷開都不影響數(shù)據(jù)的讀取.數(shù)據(jù)集的好處是降低數(shù)據(jù)庫服務(wù)器壓力,編程也簡單(其實(shí)原理大致還是用reader讀取所有數(shù)據(jù),儲存在list中)
- SqlHelper的作用,主要作用: 讀取配置文件的連接數(shù)據(jù)庫字符串,實(shí)現(xiàn)一些和數(shù)據(jù)庫的參數(shù)查詢函數(shù),傳入?yún)?shù)一般是sql命令和parameter[]參數(shù)數(shù)組
- SqlHelper的一些問題,對于0參數(shù)?DataTable?datatable =?SqlHelper?.ExecuteDataTable(sql,?new?SqlParameter[0]);
- 注意NULL和DBNULL的區(qū)別
?
一、連接字符串的寫法
l? Data Source=; 指定服務(wù)器IP(計(jì)算機(jī)名)? 服務(wù)器\實(shí)例名
l? Initial Catalog=;初始化分類,要連哪個(gè)數(shù)據(jù)庫名
l? UserId=sa;Password=sa;用戶名密碼
l? Integrated Security=true; 使用Windows驗(yàn)證方法
l? 另外一種寫法(舊):"server=.;database=”數(shù)據(jù)庫名字“;uid=sa;pwd=sa"
二、Ado.Net連接池
l? 當(dāng)?shù)谝淮蝿?chuàng)建一個(gè)連接對象并調(diào)用Open()操作的時(shí)候,該連接對象會向數(shù)據(jù)庫發(fā)出一個(gè)連接請求,并且進(jìn)行連接。
l? 當(dāng)調(diào)用該對象的Close()方法時(shí),并沒有直下關(guān)閉連接對象,而是放入了“連接池”中,
l? 當(dāng)下次再創(chuàng)建一個(gè)連接對象的時(shí)候,如果該對象所使用的連接字符串與池中現(xiàn)有的連接對象使用的字符串一模一樣(大小寫空格等都必須一樣),這時(shí),并不會直下的再創(chuàng)建一個(gè)連接,而是使用池中現(xiàn)有的對象。
l? 如果再次創(chuàng)建的連接對象所使用的連接字符串不一樣,此時(shí),則會創(chuàng)建一個(gè)新的連接。
l? 只有當(dāng)調(diào)用了連接對象的Close()方法后,當(dāng)前連接才會放入到池中。
l? 如果創(chuàng)建時(shí)和上一個(gè)連接對象一模一樣,但上一個(gè)連接并沒有Close()即:并沒有放入池中,這時(shí),也會創(chuàng)建一個(gè)連接。
三、ADO.Net中常用的幾個(gè)對象
l? SqlConnection:數(shù)據(jù)庫連接對象
l? Command:執(zhí)行SQL語句命令
l? DataReader:只讀、只進(jìn)結(jié)果集
l? DataAdapter:適配器
l? DataSet:相當(dāng)于內(nèi)存中的臨時(shí)數(shù)據(jù)庫
l? SqlDataReader對象:
n? reader.HasRow=true表明有數(shù)據(jù)
n? reader.Read() 指向下一條???? //讀取前要先Read()
n? reader[0] 獲取列的數(shù)據(jù)
n? reader[]有重載,有列索引也有列名,費(fèi)錢要求使用列索引
n? reader.GetValue(索引);
n? reader.GetOrdinal(列名);根據(jù)列名獲取列的索引
n? reader.GetInt32(索引); 直接獲取強(qiáng)類型 (有一個(gè)Null的問題)
n? int? age =reader.IsDBNull(2)?null : (int?) reader.GetInt32(2);
n? 使用時(shí)必需保證SqlConnection是打開的,不能中途關(guān)閉!
n? reader.GetInt32(索引)? 索引和查詢的順序有關(guān)!
n? 不要忘記使用using()釋放,DataReader獨(dú)享一個(gè)Connection
四、使用存儲過程
(*)封裝SqlHelper類
SqlHelper.cs是多年前微軟出品的一個(gè)使用ADO.Net方法對SQL Server數(shù)據(jù)庫進(jìn)行操作的封裝類。而我們自己手寫的SqlHelper類同樣是對數(shù)據(jù)庫訪問方法的一個(gè)封裝類庫,讓我們在訪問數(shù)據(jù)庫的時(shí)候可以很方便地調(diào)用其中封裝的方法,省略了很多重復(fù)勞動。在聲明SqlHelper的時(shí)候,我們一般會聲明為一個(gè)靜態(tài)類,不使用靜態(tài)類的話有可能產(chǎn)生一些未知的錯(cuò)誤(蘇老師說微軟說的)。
這個(gè)類中我們常用的方法如下:
除此之外,我們根據(jù)需要以及興趣也可以再增加一些其他的方法,對其進(jìn)行修改以及擴(kuò)展。
第一步、連接字符串
首先需要定義一個(gè)只讀的連接字符串,連接字符串可以直接寫死為一個(gè)固定的字符串,也可以從項(xiàng)目的配置文件中取得,一般使用后者:
private static readonly string connStr = System.Configuration.ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
這樣的話windows應(yīng)用程序的配置文件Web.config中可以配置連接字符串如下:
<configuration>
<connectionStrings>
<add name="connStr" connectionString="server=.;database=Exam;integrated security=true;"/>
</connectionStrings>
</configuration>
第二步、封裝ExcuteNonQuery
首先先寫一個(gè)完整的帶CommandType參數(shù)的方法:
public static int ExcuteNonQuery(string sql, CommandType cmdType, params SqlParameter[] sps)
{
using (SqlConnection conn = new SqlConnection(connStr))
{
using (SqlCommand cmd = conn.CreateCommand())
{
if (sps != null)
{
cmd.Parameters.AddRange(sps);
}
cmd.CommandType = cmdType;
cmd.CommandText = sql;
try
{
conn.Open();
return cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
conn.Close();
throw new Exception(ex.Message);
}
}
}
}
在這里,SqlConnection表示Sql Server數(shù)據(jù)庫的一個(gè)打開的連接,SqlCommand表示Sql Server數(shù)據(jù)庫執(zhí)行的一個(gè)sql語句或者存儲過程。然后再判斷參數(shù)數(shù)組是否為空,不為空時(shí),將參數(shù)數(shù)組加入到數(shù)據(jù)庫執(zhí)行命令中。最后打開連接,運(yùn)行ExecuteNonQuery方法。當(dāng)然,最好把最后2步try起來,捕獲異常并拋出。
??? 有了完整的ExecuteNonQuery方法,我們就可以調(diào)用它,通過指定CommandType為CommandType.Text,再封裝一個(gè)執(zhí)行Sql語句的重載:
public static int ExcuteNonQuery(string sql, params SqlParameter[] sps)
{
return ExcuteNonQuery(sql, CommandType.Text, sps);
}
第三步、封裝ExecuteScalar
ExecuteScalar與ExcuteNonQuery的使用一模一樣,只是返回值得類型為object而已,這里就不贅述了。
public static SqlDataReader ExceuteReader(string sql, CommandType cmdType, params SqlParameter[] sps)
{
SqlConnection conn = new SqlConnection(connStr);
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
if (sps != null)
{
cmd.Parameters.AddRange(sps);
}
cmd.CommandType = cmdType;
try
{
conn.Open();
return cmd.ExecuteReader(CommandBehavior.CloseConnection);
}
catch (Exception ex)
{
conn.Close();
throw new Exception(ex.Message);
}
}
}
重載方法:
public static SqlDataReader ExcuteReader(string sql, params SqlParameter[] sps)
{
return ExceuteReader(sql, CommandType.Text, sps);
}
第四步、ExceuteReader
ExceuteReader方法中返回的是一個(gè)SqlDataReader類型的對象reader,使用者拿到這個(gè)reader,再通過
while(reader.read())
{
??? ……
}
reader.close();
的方式從數(shù)據(jù)庫中一條一條地讀取數(shù)據(jù),讀完之后調(diào)用reader的close方法,在這之前,ExceuteReader中的數(shù)據(jù)庫連接不能中斷,否則數(shù)據(jù)庫連接中斷,用戶就無法從數(shù)據(jù)庫中拿到數(shù)據(jù)了,所以ExceuteReader方法中,數(shù)據(jù)庫連接的創(chuàng)建不能用using包起來,并且執(zhí)行命令的方法該這樣寫cmd.ExecuteReader(CommandBehavior.CloseConnection),CommandBehavior.CloseConnection表示在執(zhí)行該命令時(shí),如果關(guān)聯(lián)的DataReader對象被關(guān)閉,那么關(guān)聯(lián)的Connection對象也會被關(guān)閉,這樣,當(dāng)調(diào)用端調(diào)用reader.close()時(shí),數(shù)據(jù)庫連接將被關(guān)閉。
public static SqlDataReader ExceuteReader(string sql, CommandType cmdType, params SqlParameter[] sps)
{
SqlConnection conn = new SqlConnection(connStr);
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
if (sps != null)
{
cmd.Parameters.AddRange(sps);
}
cmd.CommandType = cmdType;
try
{
conn.Open();
return cmd.ExecuteReader(CommandBehavior.CloseConnection);
}
catch (Exception ex)
{
conn.Close();
throw new Exception(ex.Message);
}
}
}
重載方法:
public static SqlDataReader ExcuteReader(string sql, params SqlParameter[] sps)
{
return ExceuteReader(sql, CommandType.Text, sps);
}
第五步、ExcuteDataSet
ExcuteDataSet用于返回一個(gè)DataSet(也可以返回DataTable, 兩者區(qū)別不大)。先通過SqlDataAdapter的構(gòu)造函數(shù)聲明一個(gè)SqlDataAdapter對象da,再調(diào)用da的Fill方法,把查詢到的表放到DataSet中,最后返回這個(gè)DataSet。
public static DataSet ExcuteDataSet(string sql, CommandType cmdType, params SqlParameter[] sps)
{
using (SqlConnection conn = new SqlConnection(connStr))
{
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
if (sps != null)
{
cmd.Parameters.AddRange(sps);
}
cmd.CommandType = cmdType;
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
DataSet ds = new DataSet();
try
{
conn.Open();
da.Fill(ds);
return ds;
}
catch (Exception ex)
{
conn.Close();
throw new Exception(ex.Message);
}
}
}
}
}
上面定義da的這一大串
using (SqlConnection conn = new SqlConnection(connStr))
{
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
if (sps != null)
{
cmd.Parameters.AddRange(sps);
}
cmd.CommandType = cmdType;
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
也可以通過SqlDataAdapter的構(gòu)造方法
public SqlDataAdapter(string selectCommandText, string selectConnectionString) : this()來實(shí)現(xiàn):
SqlDataAdapter da = new SqlDataAdapter(sql, connStr);
da.SelectCommand.CommandType = cmdType;
重載方法:
public static DataSet ExcuteDataSet(string sql, params SqlParameter[] sps)
{
return ExcuteDataSet(sql, CommandType.Text, sps);
}
?
????? 相關(guān)的WPF基礎(chǔ)?
轉(zhuǎn)載于:https://www.cnblogs.com/reganLi/p/3403702.html
總結(jié)
以上是生活随笔為你收集整理的ADO.Net知识总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: keytool命令总结
- 下一篇: C语言中不检查数组下标是否越界。