之前學了幾天的SQL Server,現在用C#代碼連接數據庫了。
需要使用C#代碼連接數據庫,讀取數據。
涉及的類有:
- ConfigurationManage
- SqlConnection
- SqlCommand
- SqlDataReader
類名 | 功能 | 備注 |
ConfigurationManage | 用於讀取配置文件中的數據庫相關信息 | 沒想到備注 |
SqlConnection | 用於連接對應數據庫 | 使用前要Open,使用完畢后盡量Close |
SqlCommand | 用於存儲要執行的sql語句,並執行sql語句,獲得SQLDataReader實例或者一個int值 (該值是受影響的行數) |
每次執行前要對CommandText賦值, 也就是要執行的sql語句 |
SqlDataReader | 一行一行的去讀取數據表的元組 | 讀取元組時,只能從第一個元組開始讀,一次讀一個元組,不能回頭 |
建庫建表語句:
create database student; use student; create table student( sname nvarchar(20) not null, sno int not null, sage smallint not null, ssex char(2) not null ); alter table student add constraint PK_sno primary key (sno), constraint CK_sage check(sage between 8 and 40), constraint CK_ssex check(ssex = '男' or ssex = '女') insert into student values('張三',100, 23, '男'); insert into student values('李四',101, 24, '男'); insert into student values('王五',102, 25, '男'); insert into student values('趙六',103, 26, '男'); select * from student;
app.config配置文件中的寫法:(記得要在reference中增加引用添加命名空間,System.Configuration)
關鍵字之間的空格也不能多,比如:data source之間只有一個空格。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> </startup> <connectionStrings> <add name="constr" connectionString="Data Source=ANAN\SQLEXPRESS;Initial Catalog=student;integrated Security=True;" providerName="System.Data.SqlClient" /> <!--<add name="TestConnectionString"這個是在C#代碼里面獲取數據庫信息的key, 下面這些是數據庫的一些信息: connectionString="Data Source=你的數據庫實例名; Initial Catalog=數據庫名字;(這里不是表名,記住) User ID=sa; Password=你自己的密碼" providerName="System.Data.SqlClient" 也可以不使用密碼賬號登錄,使用Windows用戶登錄也可以/>--> <!-- integrated Security=True; 這里是使用Windows驗證的方式去連接到數據庫服務器。 這樣方式的好處是不需要在連接字符串中編寫用戶名和密碼, 從一定程度上說提高了安全性。 --> <!-- providerName="System.Data.SqlClient" 說明使用的是MSSQLServer數據庫 providerName="System.Data.SqlLite" 說明使用的是SQLLite數據庫 providerName="System.Data.OracleClient" 說明使用的是Oracle數據庫 providerName="System.Data.Oracle.DataAccess.Client" 同上,Oracle數據庫 providerName="System.Data.OleDb" 說明使用的是Access數據庫 --> </connectionStrings> </configuration>
連接數據庫的寫法,這里只是把數據打印出來,沒有做任何操作:
private static void SqlConnPrint() { StringBuilder sb = new StringBuilder("姓名\t學號\t年齡\t性別\n"); //第一步:讀取配置文件 string str = ConfigurationManager.ConnectionStrings["constr"].ToString(); //string str = @"Data Source=ANAN\SQLEXPRESS;Initial Catalog=student;Persist Security Info=True;"; //第二步:創建數據庫連接對象conn using (SqlConnection conn = new SqlConnection(str)) { //第三步:打開數據庫 conn.Open(); //第四步:創建執行sql語句的cmd對象 using (SqlCommand cmd = conn.CreateCommand()) { //第五步:構建要執行的sql語句 cmd.CommandText = "select * from student"; //第六步:執行sql語句,拿到reader對象 using (SqlDataReader reader = cmd.ExecuteReader()) { //第七步:讀取數據 while (reader.Read()) { sb.Append(reader.GetString(reader.GetOrdinal("sname")))//獲取列信息的第一種方式(知道列名) .Append("\t") .Append(reader["sno"])//第二種方式(知道列名) .Append("\t") .Append(reader[2])//第三種方式(列的知道位置,即第幾列) .Append("\t") .Append(reader.GetString(reader.GetOrdinal("ssex"))) .Append("\n"); } Console.WriteLine(sb); } } } }
打印的結果:
總結下使用SqlDataReader時應該注意以下幾點:
- SqlDataReader對象維持了一個指針,該指針最開始指向的是結果集中的第一個元組,每次調用Reader()方法都會向下挪動指針,Reader()方法返回true則說明下面還有元組,返回false說明已經讀到了最后一個元組了,這個指針只能向下挪動,不能回頭;
- SqlDataReader對象只能讀數據,不能寫數據;
- 一個SqlDataConnection只能被一個SqlDataReader對象使用,不能兩個reader對象使用同一個conn對象;
- 使用完畢盡量顯示調用Close()方法,雖然使用using代碼塊會自動幫你關閉;
- 如果要在SqlDataReader對象還未讀取完所有的結果集就要關閉SqlDataReader對象,則一個先調用Command對象的Cancel()方法,然后再顯示調用SqlDataReader對象的Close()方法。
做個一個測試,SqlDataReader是否每次調用Reader()方法都會去數據庫中讀取,結果是沒有,它是將數據讀到一個緩沖區,然后一行一行讀取這個緩沖區,所以最上面的表格中說一行行的讀取元組並不准確。
代碼上來先:
public static void ProveSqlDataReader() { String connStr = ConfigurationManager.ConnectionStrings["connStr"].ToString(); SqlConnection conn = new SqlConnection(connStr); SqlConnection conn2 = new SqlConnection(connStr); conn.Open(); conn2.Open(); SqlCommand cmd = new SqlCommand("select * from student", conn); SqlCommand cmd2 = new SqlCommand("delete student;", conn2); SqlDataReader reader = cmd.ExecuteReader(); cmd2.ExecuteNonQuery();//這里將數據庫中的數據全刪除了,但是還是打印輸出了數據表中的數據。 while (reader.Read()) { Console.WriteLine("數據: " + reader[0]); } conn.Close(); conn2.Close(); }
有關於DataSet相關的請看下一篇博客