DataSet与DataTable对象
摘自:http://www.cnblogs.com/fttbfttb/articles/1509662.html
DataSet对象
DataSet是ADO.NET中最核心的成员之一,是各种基于.NET平台程序语言(如VB.NET、C#.NET、C++.NET)的数据库应用程序开发最常接触的类,这是因为DataSet在ADO.NET实现从数据库中抽取数据的作用。数据抽取后,DataSet就是数据的存放地,它是各种数据源(SQL Server 、OLE DB等)的数据在计算机内存的缓存,所以有时说DataSet可以看成是一个数据容器(又称数据集)。在客户端通过对DataSet的数据集读取、更新等操作,从而实现对数据源的同等操作。
DataSet的最大优点是离线(断开)和连接。DataSet既可以以离线方式,也可以以实时连接方式来操作数据库中的数据。这样的好处是大大减少了服务器端数据库的连接线程,从而大大地减少了服务器端的运行压力。所以,在数据量不大的情况下,使用DataSet是最好的选择。
DataSet的基本工作过程:应用程序一般并不直接对数据库进行操作(直接在程序中调用存储过程等除外),而是先完成和数据库的连接,接着通过数据适配器(DataAdapter)把数据库中的数据填入DataSet对象,然后客户端再通过读取DataSet来获得需要的数据,同样,在更新数据库中的数据时,也是首先更新DataSet,然后再通过DataSet和数据适配器将更新的数据同步地解释入数据库中。
DataSet中的几个重要对象:
TablesCollection对象:DataSet 里的表用DataTable来表示,一个DataSet里面可以包含多个DataTable,这些DataTable就构成了 TablesCollection对象。每个DataTable中都包含一个ColumnsColleciton和一个RowsCollection对 象。
RelationsCollection对象:各个DataTable之间的关系通过DataRelation来表达,这些DataRelation构成的集合就是RelationsCollection对象。
ExtendedProperties对象:这个对象用来定义特定的信息,比如密码、更新时间等。
DataTable对象
每一个DataSet都是一个或多个DataTable 对象的集合(DataTable相当于数据库中的表),这些对象由数据行(DataRow)、数据列(DataColumn)、字段名(Column Name)、数据格(Item),以及约束(Constraint)和有关DataTable对象中数据的关系(Relations)与数据显示排序(DataView)信息组成。
DataView用来在观察数据时提供排序和过滤的功能。DataColumn用来对表中的数据值进行一定的规限。比如哪一列数据的默认值是什么、哪一列数据值的范围是什么、哪个是主键、数据值是否是只读等。
由于一个DataSet可能存在多张表,这些表可能存在关联关系,因此用parentRelations和childRelations来表述。ParentRelations表是父表,childRelations是子表,子表是对父表的引用,这样就使得一个表中的某行与另一个表中的某一行甚至整个表相关联。
1.DataSet操作
①用DataAdapter填充
DataSetDataSet ds = new DataSet();
adapter.Fill(ds);
adapter.Fill(ds, "表名"); //用一个表去填充DataSet.
②合并两个DataSet
myConnection.Open();
string strSQL = "SELECT * FROM P_Product";
DataSet ds1 = new DataSet();
SqlDataAdapter adapter1 = new SqlDataAdapter(strSQL, myConnection);
adapter1.Fill(ds1, "Product");
strSQL = "SELECT * FROM P_Category";
DataSet ds2 = new DataSet();
SqlDataAdapter adapter2 = new SqlDataAdapter(strSQL, myConnection);
adapter2.Fill(ds2, "Category");
myConnection.Close();
//ds1就是合并后的DataSet
ds1.Merge(ds2, true, MissingSchemaAction.AddWithKey);
GridView1.DataSource = ds1.Tables["Product"];
GridView1.DataBind();
GridView2.DataSource = ds1.Tables["Category"];
GridView2.DataBind();
2.DataTableCollection操作
表示 DataSet 的表的集合。
DataTableCollection dtc = ds.Tables;
DataTable customerTable = dtc["Product"];
3.DataRelation操作
//创建DataRelation
DataRelation dr;
DataColumn parentCol;
DataColumn childCol;
parentCol = ds.Tables["Customers"].Columns["CustomerID"];
childCol = ds.Tables["Orders"].Columns.["CustomerID"];
dr = new DataRelation("CustOrders", parentCol, childCol);
ds.Relations.Add(dr);
currentParentRow = ds.Tables["Customers"].Rows[DataGridName.SelectedIndex];
foreach(DataRow r in currentParentRow.GetChildRow("CustOrders"))
{
Lable1.Text += r["OrderID"] + ",";
}
//DataRelation实现父子表(范例)
if (!IsPostBack)
{
using (OleDbConnection con = new OleDbConnection(cn))
{
DataSet ds = new DataSet();
OleDbDataAdapter dr1 = new OleDbDataAdapter("select * from km", con);
OleDbDataAdapter dr2 = new OleDbDataAdapter("select * from km1", con);
dr1.Fill(ds, "tb1");
dr2.Fill(ds, "tb2");
ds.Relations.Add("newtb", ds.Tables[0].Columns["id"], ds.Tables[1].Columns["flag"]);
Repeater1.DataSource = ds;
Repeater1.DataBind();
}
}
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<div class="adminleft" id='admin<%# Eval("id") %>'>
<h2 id='h<%# Eval("id") %>' onmouseout="fff('h<%# Eval("id") %>')" onmouseover="f('h<%# Eval("id") %>')" onclick="javascript:location.href='showbj.aspx?flag=<%# Eval("id") %>&na=<%# Eval("subject") %>'"><%#Eval("subject") %></h2>
<ul>
<asp:Repeater ID="Repeater2" runat="server" DataSource='<%# ((DataRowView)Container.DataItem).Row.GetChildRows("newtb") %>' OnItemCommand="Repeater1_ItemCommand">
<ItemTemplate>
<li><asp:LinkButton ID="LinkButton1" runat="server" CommandArgument='<%#Eval("[\"flag\"]") %>' CommandName="re"><%#Eval("[\"subject\"]") %></asp:LinkButton></li>
</ItemTemplate>
</asp:Repeater>
</ul>
</div>
</ItemTemplate>
</asp:Repeater>
4.DataTable操作
①创建一个DataTable
DataTable MyTable;
MyTable = new DataTable ("Test");
MyTable.CaseSensitive = False;//是否区分大小写
MyTable.MinimumCapacity = 100;//数据库的最小记录空间
②创建表列
DataTable MyTable;
DataColumn MyColumn;
MyTable = new DataTable ("表名");
MyColumn = MyTable.Columns.Add("列名",typeof(string));
MyColumn = MyTable.Columns.Add("列名",typeof(int));
③创建表达式列
//方法一
DataColumn tax = new DataColumn();
tax.DataType = typeof(Currency);
tax.Expression = "total*rate*0.20";
//方法二
MyTable.Columns.Add("tax", typeof(Currency), "total*rate*0.20");
④从DataTable中删除DataRow对象
(1)DataRowCollection对象的Remove方法
DataRow drEmployee = dtEmployees.Rows(3);
dtEmployees.Rows.Remove(drEmployee);
(2)DataRow对象的Delete方法
drEmployee.Delete;
比较:Remove方法时从DataRowCollection中删除DataRow,而Dalete方法只是对删除的行做标记。
DataRow类包括RowState属性。RowState属性值表示从第一次创建DataTable(或从数据库加载DataTable)开始,行是 否发生更改,如何更改以及通过何种方式更改。属性的可选值:Modified | Detached | Added。
⑤DataTable进行动态的筛选和排序
(1)获取所有行。
- DataRow[] rows = dt.Select();
(2)按主键顺序(如没有主键,则按照添加顺序)获取符合筛选条件的行。
- DataRow[] rows = dt.Select("ID>52");
(3)获取符合筛选条件的行,并按指定的排序条件排序。
- DataRow[] rows = dt.Select("ID>52","ID DESC");
(4)获取符合筛选条件和指定状态的行,并按指定的排序条件排序。
- string strExpr = "ID>52";
- string strSort = "ID DESC";
- DataRow[] foundRows = dt.Select(strExpr, strSort,
DataViewRowState.OriginalRows);
⑥DataTable进行数据统计
我们在使用SQL Server时,可以轻松地对数据进行Sum、Aver、Count等操作以获得统计结果,那么,在已经把数据检索出来的DataSet(DataTable)中如何进行统计呢?特别是通过第三方接口Web Service获得了DataSet,这个时候,没有办法去执行Select语句来获取这些统计,怎么办呢?
办法总比问题多,其实在DataTable中也是可以进行数据统计的。
下面就通过几个简单的示例,介绍一下如何无须通过逐条记录进行计算就可以轻松地获得DataTable中的记录统计结果。这里调用的是功能强大的DataTable的函数Compute。
(1)函数说明:
- public object Compute(string strExpression,string strFilter);
strExpression:要计算的表达式字符串,基本上类似于Sql Server中的统计表达式。
strFilter:统计的过滤字符串,只有满足这个过滤条件的记录才会被统计。
(2)调用示例。
假设一个产品销售表P_Sell,描述商场中各销售人员的销售记录,如表5-2所示。
表5-2 产品销售表
序号 |
列名 |
数据类型 |
长度 |
主键 |
允许空 |
说明 |
1 |
ID |
int |
4 |
√ |
流水号 |
|
2 |
Name |
varchar |
50 |
√ |
姓名 |
|
3 |
Sex |
smallint |
2 |
√ |
性别:0为女,1为男 |
|
4 |
Birthday |
datetime |
8 |
√ |
生日 |
|
5 |
ProductId |
varchar |
20 |
√ |
销售产品代码 |
|
6 |
Num |
int |
4 |
√ |
销售的数量 |
|
7 |
Price |
decimal |
9 |
√ |
销售价格 |
统计所有性别为女的销售员的数量:
- object n = table.Compute("count(ID)", "Sex = 0");
统计所有年龄大于20岁的销售员的数量:
- int c=(int)table.Compute("count(ID)",
- "Birthday<'" + DateTime.Today.AddYears(-20)+"'");
统计销售产品的平均价格:
- decimal ap=(decimal)table.Compute("avg(Price)", "true");
统计产品代码为1的产品销售数量:
- object m = table.Compute("sum(Num)", "ProductId='sj'");
统计所有产品的销售总金额:要统计销售总金额,table中不存在某项产品某个促销员销售的金额数据,但我们可以通过Quantity*Price来获得。比如table.Compute("Sum(Quantity*Price)","true");。
这里有一个问题是,DataTable的统计功能没有SqlServer强大,这个写法是错误的! 因为Compute的统计不具备Sum(Quantity*Price)这样的数据的功能。那怎么办呢?
对于这样复杂数据的统计,我们可以通过在DataTable中创建一个新的DataColumn来完成,比如为"total",同时设置该字段的Expression为Quantity*Price,这样我们就可以使用统计功能了。
- DataColumn dc = new DataColumn("total", Type.GetType("System.Decimal"));
- dc.Expression = "Num*Price";
- table.Columns.Add(dc);
- object s=table.Compute("sum(total)", "true");
当然,这个功能也可以通过 DataGrid增加一个模板列,在ItemDataBind事件里实现计算。
⑦.合并两个DataTable表的数据
- DataTable dt1 = ds.Tables[0];
- DataTable dt2 = ds.Tables[1];
- dt1.Merge(dt2, true, MissingSchemaAction.AddWithKey);
5.DataView操作
DataView就时数据视图,为数据库结构提供了外模式的实现。同时DataView也可以为窗体控件和Web控件提供数据绑定功能,在每一个DataTable中内建了一个DataView为:DataTable.DefaultView()。
(1)得到DataView。
- DataView dv = ds.Tables[0].DefaultView;
- //或
- DataView dv = new DataView(ds.Tables["Product"], "ID > 52", "ID DESC",
- DataViewRowState.CurrentRows);
(2)得到DataView的行数据。
- foreach (DataRowView rowview in dv)
- {
- for (int i = 0; i < dv.Table.Columns.Count; i++)
- {
- Response.Write(rowview[i] + "
"); - }
- }
(3)对结果集过滤排序。
- DataView dv = ds.Tables[0].DefaultView;
- dv.RowFilter = "ID > 52";
- dv.Sort = "ID DESC";
- int c = dv.Count;
- if (c > 51)
- {
- for (int n = 50; n < c; n++)
- {
- dv.Delete(n);
- }
- }
- this.DataGrid1.DataSource = dv;
6.绑定数据操作
GridView.DataMember = "Authors";
GridView.DataBind();
GridView.DataBind();
dv.RowFilter = "state = 'CA'";
GridView.DataSource = dv;
GridView.DataBind();