上一篇我們講了dataset的內部構成和如何往裡面填充數據.當一個dataset被填充上數據後我們就可以用個數據綁定控件來綁定到dataset裡的datatable了,然後就可以顯示出裡面的數據了.比如:GridView1.DataSource = ds.Tables[0].DefaultView,這樣數據被顯示出來了.很奇怪ds.Tables[0].DefaultView怎麼多個DefaultView這玩意.有什麼作用?我們把它去掉直接用ds.Tables[0]發現也可以.那這個東西有什麼用?官方的解釋是:獲取可能包括篩選視圖或游標位置的表的自定義視圖.
簡單的說就是:獲取表的視圖.什麼叫表的視圖?表指的就是datatable,也就是datatable的視圖.datatable就是datatable還要視圖干什麼?有什麼作用?可以這麼解釋,datatable是存放是數據的,而且存放在內存中,可以被程序去處理.但是datatable並不能把這些數據呈現出來被我們肉眼看到.那我們要把這些數據顯示出來被我們看到,那就要用視圖了.視圖嘛,字面意思就是,可視化圖形的意思.現在知道,視圖的作用就是把datatable裡的數據顯示出來能被我們看到的.為了能有個形象的理解,打個不准確的比喻吧.水,是無色透明的.那麼我們怎麼能看到水呢?
我們用個杯子去裝水,是不是就能看到水的形狀了.是什麼形狀呢?當然取決於杯子的形狀,用圓形杯子裝水,我們看到的水的形狀就是圓柱體的.用方形杯子裝水,我們看到的水形狀就是立方體的.現在我告訴你,datatable裡的數據就相當於水,視圖就相當於杯子.那麼要讓數據(水)顯示出來給我們看到,是不是要用個視圖(杯子)去裝數據啊.現在是否對視圖有個感性的認識了,它的主要作用就是顯示數據的.說白了視圖就是格式化輸出數據的.可以聯想到html語言就相當於視圖,而裡面的文字就相當於數據.例如在html中有:<b>數據</b>那麼'數據'二字顯示的就是粗體的.為什麼顯示粗體?因為html(視圖)能讓它(數據)顯示,並能控制它(數據)顯示的樣式.(插一句,html的作用是用來顯示數據的(圖片,文字.等等都行)的,那麼數據放哪呢?
可以從數據庫裡讀出數據來然後通過html顯示,也可以把數據存放xml文件裡,現在就很流行用xml來存放數據,用html來顯示.也就是xml+html技術.xml現在是很火的一個東東,後面我們再詳細探討探討xml的一些知識).上面講了那麼多廢話無非是想說:視圖是用來顯示數據的.那麼我有個視圖沒有數據,可有意義?沒有.光有視圖沒有任何數據,視圖去顯示誰呢?就是無用的廢物了.那麼我們有數據沒有視圖可有意義呢?有,我們不想顯示這些數據,就不一定非要搞個視圖了吧.
可見,我們有個視圖必然要有數據才有意義.程序中就是這樣,有視圖肯定有數據.而數據我們可以想象成就裝在視圖中(水裝在杯子中嘛),我們就一組數據,可以搞幾個不同的視圖啊,當把數據放到不同的視圖裡,顯示出來的就是不一樣的效果的.同樣,把一個視圖改變了那麼這個視圖裡的數據顯示出來的的樣式就改變了,可見視圖對數據來說還是瞞重要的一個東西.在程序中,視圖不僅能顯示數據,也能實現對數據的增刪改查.因為可以看做數據裝在視圖裡嘛,視圖當然能對數據進行操作.回想下,我們說過dataset可以看做是個小型的數據庫.既然是數據庫,肯定能增刪改查嘛,怎麼做到呢?把數據放到視圖裡用視圖來操作.
(上面說的真是夠羅嗦了,發現我越來越唐僧了,只怪我腦子不靈活,理解能力差,所以把知識表達的容易理解才行)
好了講了這麼多,我們來看看在程序中到底怎麼去用視圖.
在程序中,表示視圖的類是:DataView.也就是說在程序中DataView就是視圖,那麼數據呢,數據當然是datatable中的數據,而datatable只管把數據裝起來,不會顯示.所以我們可以創建一個視圖把datatable放到視圖裡,也就是把數據放進去了.(datatable 可以想象成一個無形的表)
程序中創建一個視圖就是 DataView dv = new DataView(),當然僅有視圖沒數據是沒有意義的.所以我們創建視圖的時候,都裝載一個datatable進去,像這樣創建的DataView dv = new DataView(datatable).這樣就是把datatable配套一個視圖對象(dataview)了.
上面說了,視圖可以控制變數據的顯示樣式的.我把視圖的排列方式改變了,那麼數據顯示出來的樣式也就改變了.DataView中有個方法叫DataView.Sort(),就是用來對數據排序的.可形象的想象為DataView裡面是一層一層的像書架一樣.書就是數據擺在書架的層上.調用這個方法後,相當於把書架裡的每層按規律換一下.(上層換到下層...)
我們看看下面代碼,代碼中我們創建一個dataset,然後添加兩個表分別是table1和table2,table1是學生表,有兩個字段,id和name;table2是借書表,裡有三個字段,id,tb1_id,bookname.然後用gridview1綁定到table1,用gridview2綁定到table2.
我們對table2進行排序,把table2裡的字段添加到DropDownList中,我們通過選擇DropDownList裡的值,來設定按哪個字段來排序.
代碼如下:
1 static DataView dv;
2 static DataSet ds;
3 protected void Page_Load(object sender, EventArgs e)
4 {
5 if (!Page.IsPostBack)
6 {
7 ds = new DataSet();
8
9 DataTable table1 = new DataTable("tb1");
10 DataTable table2 = new DataTable("tb2");
11
12 ds.Tables.Add(table1);
13 ds.Tables.Add(table2);
14
15 table1.Columns.Add("id", typeof(int));
16 table1.Columns.Add("name", typeof(string));
17
18 DataRow dr = table1.NewRow();
19 dr["id"] = 1;
20 dr["name"] = "張三";
21 table1.Rows.Add(dr);
22
23 //給table1添加一行的另一種寫法
24 table1.Rows.Add(2, "李四");
25
26 table2.Columns.Add("id", typeof(int));
27 table2.Columns.Add("tb1_id", typeof(int));
28 table2.Columns.Add("bookname", typeof(string));
29
30 table2.Rows.Add(1, 1, "高等數學");
31 table2.Rows.Add(2, 1, "大學英語");
32 table2.Rows.Add(3, 2, "平凡的世界");
33 table2.Rows.Add(4, 2, "追風筝的人");
34 table2.Rows.Add(5, 2, "堂吉可德");
35
36 //此方法必須調用,否則後面用篩選器時無效
37 table2.AcceptChanges();
38
39 //創建一個視圖,作用table2裡的數據
40 dv = new DataView(table2);
41
42 //把table2裡的列添加到DropDownList1中
43 DropDownList1.Items.Clear();
44 DropDownList1.Items.Add("請選擇");
45 foreach (DataColumn dc in table2.Columns)
46 {
47 DropDownList1.Items.Add(dc.ToString());
48 }
49
50 GridView1.DataSource = ds.Tables["tb1"].DefaultView;
51 GridView1.DataBind();
52 GridView2.DataSource = ds.Tables["tb2"].DefaultView;
53 GridView2.DataBind();
54 }
55
56 }
57
58 //排序
59 protected void Button2_Click(object sender, EventArgs e)
60 {
61 //設定要排序的列
62 dv.Sort = DropDownList1.SelectedItem.Text;
63
64 GridView2.DataSource = ds.Tables["tb2"].DefaultView;
65 GridView2.DataBind();
66 }
67
運行後,我們從DropDownList1裡選個列,點排序按鈕(button2),沒反應,怎麼搞都沒反應就是不排序,怎麼回事?我們看看64行代碼:GridView2.DataSource = ds.Tables["tb2"].DefaultView. DefaultView是什麼意思?它的意思是,當我們在dataset添加一個表個時候,會自動創建一個視圖給這個表,也就是默認的視圖.DefaultView的意思,就是默認的視圖.ds.Tables["tb2"].DefaultView. DefaultView當然就是table2表的默認視圖.看看我們排序的是哪個視圖,是我們創建的dv啊.dv和DefaultView是兩個不同的視圖,dv進行排序了,DefaultView又沒有排序GridView2綁定到默認視圖上有什麼用呢?同樣,直接這麼寫GridView2.DataSource = ds.Tables["tb2"]也不行,因為這麼寫相當於只給GridView2提供了數據,而用的試圖是GridView2裡的(GridView這麼強大的控件是能提出視圖能力的).
那我們改下:
//排序
protected void Button2_Click(object sender, EventArgs e)
{
//設定要排序的列
dv.Sort = DropDownList1.SelectedItem.Text;
GridView2.DataSource = dv;
GridView2.DataBind();
}
這樣就可以了,讓GridView2綁定到dv視圖上,因為用dv來排序的.我們不這樣改也行,我們依然把GridView2綁定到table2的默認視圖上(DefaultView)我們對這個DefaultView進行排序上一樣的.看下面代碼,效果是一樣的
1 //排序
2 protected void Button2_Click(object sender, EventArgs e)
3 {
4 //設定要排序的列
5 //dv.Sort = DropDownList1.SelectedItem.Text;
6
7 //GridView2.DataSource = dv;
8 //GridView2.DataBind();
9
10 //用table2的默認視圖來排序
11 ds.Tables["tb2"].DefaultView.Sort = DropDownList1.SelectedItem.Text;
12
13 GridView2.DataSource = ds.Tables["tb2"].DefaultView;
14 GridView2.DataBind();
15 }
16
上面說了,視圖單獨存在沒有意義,它要對數據操作才有意義.視圖不僅能顯示數據,還能按一定排列方式顯示數據,還可以對數據進行增刪改查,我們用代碼來說明怎麼進行這些操作,理解了視圖後這些就很簡單了.
1 //通過視圖給table2增加一行
2 protected void Button1_Click(object sender, EventArgs e)
3 {
4 DataRowView drv = dv.AddNew();
5 drv["id"] = 100;
6 drv["tb1_id"] = 2;
7 drv["bookname"] = "張愛玲散文集";
8
9 GridView2.DataSource = dv;
10
11 //大家考慮下添加一行數據後,直接綁定到datatable數據中是否可以(也就是dataview添加一行,是否把數據添加到databale中了)
12 //GridView2.DataSource = ds.Tables["tb2"];
13 GridView2.DataBind();
14 }
15 //通過視圖刪除table2一行
16 protected void Button3_Click(object sender, EventArgs e)
17 {
18 //刪除最後一行
19 dv.Delete(dv.Count - 1);
20
21 GridView2.DataSource = dv;
22 GridView2.DataBind();
23
24 }
25 //通過視圖更改table2一行
26 protected void Button4_Click(object sender, EventArgs e)
27 {
28 //更新第0行bookname列
29 dv[0]["bookname"] = "如來神掌";
30
31 GridView2.DataSource = ds.Tables["tb2"];
32 GridView2.DataBind();
33
34 }
35 //在視圖中查找
36 protected void Button5_Click(object sender, EventArgs e)
37 {
38 //設置要查的列
39 dv.Sort = "bookname";
40 //在視圖中找
41 string str = dv.Find("追風筝的人").ToString();
42
43 Response.Write("第"+str+"行");
44 }
45
上面代碼我們講了利用視圖對數據進行增刪改查,理解視圖與數據的關系後上面的就很容易理解了.下面我們在看看視圖對數據的篩選功能,什麼叫篩選?顧名思義,就是從一堆東西裡得到符合條件的,不符合條件的就不要.其實就是按條件查詢的意思.....
dataview裡有個屬性RowFilter,這個屬性就是接受條件的,看下面代碼:
1 protected void Button6_Click(object sender, EventArgs e)
2 {
3 //設置篩選條件
4 dv.RowFilter = TextBox1.Text;
5
6 GridView2.DataSource = dv;
7 GridView2.DataBind();
8
9 }
10
當我們在textbox1裡輸入像這樣的條件:bookname='大學英語' ,那麼視圖就只讓符合這個條件的那行顯示,gridview2綁定上視圖就行了.
此外視圖還能對數據的版本進行篩選,什麼叫數據的版本,比如我們在數據裡刪除一行,那麼視圖可以顯示刪除的那一行.還可以顯示 未更改的行啊等等.剛才說了還能顯示視圖已刪除的行,數據已經刪除了怎麼還能顯示呢?其實視圖刪除一行數據只不過是在視圖中把刪除的那行做了個記號,並未真正刪除數據中那行.同樣我們修改一行數據後,視圖也會在修改的這行中加個記號,增加一行視圖也會加個記號的.獲得相應的記號,就能得到相應記號的行了.我們來看段代碼:
1 protected void Button6_Click(object sender, EventArgs e)
2 {
3 //設置篩選條件
4 //dv.RowFilter = TextBox1.Text;
5
6 //通過刪除記號(Deleted)來設置讓篩選器顯示被刪除的行
7 dv.RowStateFilter = DataViewRowState.Deleted;
8
9 GridView2.DataSource = dv;
10 GridView2.DataBind();
11
12 }
13
當刪除tabel2中的數據時候,上面的代碼就可以把刪除的顯示出來了.當然還可以顯示新增加數據等.要注意的是要想用這篩選器,在創建好table2表後必須要調用一個方法table2.AcceptChanges()否則,顯示不出來篩選的數據,至於為什麼?請大家找微軟....
關於dataview上面就泛泛的說了個大概...
下面我們說說dataset裡的關系
上篇文章中說到,dataset由datatale和關系構成.關系就是datatable與datatable之間的關系.那麼肯定一個dataset裡不止一個表才存在表與表之間的關系.上面的列子恰好一個dataset裡有兩張表,一個是學生表(table1),另一個是學生借書表(table2),table2中有學生的id號(tb1_id),那麼table1與table2就通過這個id有了關系.對於table2來說它裡面的學生id(tb1_id),也是它的外鍵啊.table1與table2這樣一種關系我們是心理明白的,但是程序並不知道,所以我們要在dataset裡創建關系.
怎麼創建?看下面代碼:
1 //創建關系
2 protected void Button7_Click(object sender, EventArgs e)
3 {
4 //創建一個父/子這樣的關系,關系的名字叫:tb12
5 System.Data.DataRelation tb12 = new DataRelation("tb12", ds.Tables["tb1"].Columns["id"], ds.Tables["tb2"].Columns["tb1_id"]);
6 //把創建的關系添加到dataset的關系集合中
7 ds.Relations.Add(tb12);
8
9 //也可以通過這個寫法來添加關系
10 //ds.Relations.Add("tb12", ds.Tables["tb1"].Columns["id"], ds.Tables["tb2"].Columns["tb1_id"]);
11 }
12
上面代碼就是在dataset裡添加了一個名為"tb12"的關系,一看便知道怎麼創建了,創建好了怎麼用?
第一個表table1裡一個學生借了什麼書,就可以通過剛才建立的關系來得到了.我們指定table1裡一行(例如:table1.Rows[0]第0行),而datarow有個方法叫GetChildRows("關系名"),然後這個第0行就能通過關系,找到,它在table2裡所有子行了.
看如下代碼:
1 //得到子集
2 protected void Button8_Click(object sender, EventArgs e)
3 {
4 //創建一個表,2列的
5 DataTable dt = new DataTable();
6 dt.Columns.Add("name", typeof(string));
7 dt.Columns.Add("bookname", typeof(string));
8
9 //指定table1裡行號,指定好行號後就用這行調用dr.GetChildRows("關系名")方法,即可得到此行在table2裡的子集
10 int row=int.Parse(TextBox1.Text);
11 DataRow dr= ds.Tables["tb1"].Rows[row];
12
13 //用上面table1裡的一行,調用方法,得到此行在table2裡子行的集合(可能table2裡有很多行都是它的,所以返回的是數組)
14 DataRow[] drs = dr.GetChildRows("tb12");
15 foreach (DataRow ddr in drs)
16 {
17 //取出table1某行在table2裡的子集,並添加到一個新表裡(dt)
18 dt.Rows.Add(dr["name"], ddr["bookname"]);
19 }
20
21 GridView3.DataSource = dt;
22 GridView3.DataBind();
23 }
24
上面就是簡單的利用dataset的裡表與表之間的關系的例子.通過關系,可以得到父表中某行在子裡的子行.(用id來建立關系的)
好了,關於dataview和關系就講怎麼多,這次說不是很好,估計會看的暈暈的.
說到現在dataset,發現都是我們自己往dataset裡加數據,等於自己和自己玩,我們更多的時候希望能從數據庫裡讀取數據放到dataset裡,然後處理數據後再一下更新到數據庫裡.那麼怎麼把數據裡的數據讀取到dataset裡呢?前面講的SqlDataReader類可以從數據裡得到數據,然後再一行一行的得到記錄,再把字段對應的值得到,添加到dataset裡的datatable裡.這樣是不是麻煩了點,而且效率也稍微慢了點,因為一次只能操作一行數據,還要保持程序與數據的連接.那麼能不能一下就把數據庫的數據裝到dataset裡呢?SqlDataAdapter類就能做到,下次就探討一下SqlDataAdapter的用法和數據訪問的並發控制.