在项目中,经常会遇到这样的问题。用SQL从数据库中选出需要的数据存入DataTable之后,需要进行一定的处理之后,才可以用来显示在页面上。
之前对这些问题,都是遇到一个就百度一个,没有系统的处理这些问题,今天就写个文档来处理一下这个问题
先来几个简单的喽。
添加列和行:
(既然是整理, 那就写全一点吧,三个方法)
#region 方法一: DataTable tblDatas =new DataTable("Datas"); //表名 DataColumn dc =null; dc = tblDatas.Columns.Add("ID", Type.GetType("System.Int32")); dc.AutoIncrement =true;//自动增加 dc.AutoIncrementSeed =1;//起始为1 dc.AutoIncrementStep =1;//步长为1 dc.AllowDBNull =false; //不允许为空 dc = tblDatas.Columns.Add("Product", Type.GetType("System.String")); dc = tblDatas.Columns.Add("Version", Type.GetType("System.String")); dc = tblDatas.Columns.Add("Description", Type.GetType("System.String")); // DataRow newRow; newRow = tblDatas.NewRow(); newRow["Product"] ="这个地方是单元格的值"; newRow["Version"] ="2.0"; newRow["Description"] ="这个地方是单元格的值"; tblDatas.Rows.Add(newRow); newRow = tblDatas.NewRow(); newRow["Product"] ="这个地方是单元格的值"; newRow["Version"] ="3.0"; newRow["Description"] ="这个地方是单元格的值"; tblDatas.Rows.Add(newRow); #endregion
看完一个方法,也许会问 dc = tblDatas.Columns.Add("Product", Type.GetType("System.String")); 为什么要用 dc= 这个东西啊 tblDatas.Columns.Add("Product", Type.GetType("System.String")); 直接用之个也可以啊。确实,这样也是可以的,用 dc= 是为了方便给这个列设置属性。比如,我要设置这个列不能为空 我就可以 dc.AllowDBNull =false; 就像第一列一样
#region 方法二: DataTable tblDatas =new DataTable("Datas"); tblDatas.Columns.Add("ID", Type.GetType("System.Int32")); tblDatas.Columns[0].AutoIncrement =true; tblDatas.Columns[0].AutoIncrementSeed =1; tblDatas.Columns[0].AutoIncrementStep =1; tblDatas.Columns.Add("Product", Type.GetType("System.String")); tblDatas.Columns.Add("Version", Type.GetType("System.String")); tblDatas.Columns.Add("Description", Type.GetType("System.String")); tblDatas.Rows.Add(newobject[] { null, "a", "b", "c" }); tblDatas.Rows.Add(newobject[] { null, "a", "b", "c" }); tblDatas.Rows.Add(newobject[] { null, "a", "b", "c" }); tblDatas.Rows.Add(newobject[] { null, "a", "b", "c" }); tblDatas.Rows.Add(newobject[] { null, "a", "b", "c" }); #endregion
这个方法没有使用到 dc= 所用设置属性的时候 就要tblDatas.Columns[0].AutoIncrement =true; 这样去设置, 个人觉得比较麻烦。这个就是给Table的列赋值的时候,一次把一行的数据按照顺序全加进去。而第一个方法就是一列一列的辅助,那样的话 就比较麻烦。dt.Rows.Add(new object[] { null, "Tang", "W", "25", "50" });这里第一个值赋值的是NULL 是因为这是一个自动添加列 所以要赋值为NULL
#region 方法三: DataTable table =new DataTable(); //创建table的第一列 DataColumn priceColumn =new DataColumn(); priceColumn.DataType = System.Type.GetType("System.Decimal");//该列的数据类型 priceColumn.ColumnName ="price";//该列得名称 priceColumn.DefaultValue =50;//该列得默认值 // 创建table的第二列 DataColumn taxColumn =new DataColumn(); taxColumn.DataType = System.Type.GetType("System.Decimal"); taxColumn.ColumnName ="tax";//列名 taxColumn.Expression ="price * 0.0862";//设置该列得表达式,用于计算列中的值或创建聚合列 // 创建table的第三列 DataColumn totalColumn =new DataColumn(); totalColumn.DataType = System.Type.GetType("System.Decimal"); totalColumn.ColumnName ="total"; totalColumn.Expression ="price + tax";//该列的表达式,是第一列和第二列值得和 // 将所有的列添加到table上 table.Columns.Add(priceColumn); table.Columns.Add(taxColumn); table.Columns.Add(totalColumn); //创建一行 DataRow row = table.NewRow(); table.Rows.Add(row);//将此行添加到table中
这个方法相对来说用的比较少,但是也很有用,比如 我从DB 中选取到一个字段,当我绑定到页面的时候,我添加几个字段(百分比,总和)就可以在Table中添加一个列 totalColumn.Expression ="price + tax"; 用这种方法去计算。
操作Table中的数据当然会用到 Select 方法了。下面就说说 这个方法。
Select方法
首先select这个方法,一共有四个重载的函数
1:Select()
2:Select(string filterExpression)
3:Select(string filterExpression, string sort)
4:Select(string filterExpression,string sort, DataViewRowState record States)。
说白了,用这个方法只需要了解这几个参数是什么意思 就没有什么大问题了。那就一个一个来
1:select()
这个没参数,就没得说了。就是把DataTable中的数据都选出来。但要注意的是,select方法选出的都是DataRow 对象的数组。这个没有参数的使用的相对来说比较少。
2:Select(string filterExpression)
这个filterExpression 就是一个表达式。这个就要研究一下了。表达式支持“and, Like, or”
比如
Select("id>='3' and name='hello'"); (选出id这个字段大于等于3并且name 等于“hello”的数据)
Select("id>='3' or id='1'"); (选出id大于等于3 或者id等于1的数据)
Select("name like '%hello%'");(选出name用hello的数据)
3:Select(string filterExpression, string sort)
这个方法中的sort是排序的意思。就是你用表达式选出DataRow的数据之后,可以用sort这个参数来对这些数据进行排序。
就是在第二个方法的基础上再加一个排序的功能喽 Select("id>='3' or id='1'","id desc"); 按照id 降续排列。
4:Select(string filterExpression,string sort, DataViewRowState record States)。
这个有加了一个参数,叫行状态。这个什么东西啊,MSDN 是这样说的https://msdn.microsoft.com/zh-cn/library/system.data.dataviewrowstate.aspx,DataViewRowState 是一个枚举类型(有兴趣的可以看看)
成员名称 | 说明 | |
---|---|---|
Added |
一个新行。 |
|
CurrentRows |
包括未更改行、新行和已修改行的当前行。默认情况下,DataViewRowState 项设置当前行。 |
|
Deleted |
已删除的行。 |
|
ModifiedCurrent |
已修改的原始数据的当前版本(请参见 ModifiedOriginal)。 |
|
ModifiedOriginal |
已修改的数据的原始版本。(尽管此数据已被修改,它仍作为 ModifiedCurrent 可用)。 |
|
None |
无。 |
|
OriginalRows |
包括未更改行和已删除行的原始行。 |
|
Unchanged |
未更改的行。 |
总结一下这个Select方法,你可能会发现,这个filterExpression的参数是查询的限定式。相当于SQL查询语言中的WHERE语句,其语法符合SQL语法 。
Select方法是不区分大小写的(字段名不区分),如果需要区分大小写,需要将DataTable的caseSensitive属性设为true。
Select方法的返回的是包含查询到的数据的DataRow数组,但是这个DataRow只是被查询的DataTable的一个映射,所以DataRow是随着DataTable的行变化而变化的。例如,DataTable的行都被删除了,那么DataRow中的数据同样被删除了(即便是先Select,再删除的)
所以,要想把返回的DataRow放进数据显示控件中,需要将其放入另一个DataTable中,如果直接放入原DataTable或将原DataTable的行全部清除再放入查询所得的数据都是不行的,程序会显示错误,错误提示是“表中已有此行”。就要把选出来的DataRow放在新建的表中。
另外,在一个新表中插入行,不能直接用DataTable.Rows.Add(DataRow)的方式,因为这样是插入一个新表,也就是DataRow是空的(简单说就是没有列)。要用导入行的方式,DataTable.ImportRow(DataRow)。当然,前提是这个新表要有与原数据表一样的结构。
那么问题就来了,怎么创建一个与原数据表一样结构的表,DataTable中有两个方法DataTable.Clone() ;DataTable.Copy();
DataTable.Clone() 这个只会克隆表的结构(也就是列)
DataTable.Copy() 这个不仅会有表的结构还有表中的数据。
所以呢,就很明显了,DataTable dtClone = dt.Clone() ; 先创建一个与原数据表一样结构的表,然后再讲select出来的数据添加到表中,记得要用DataTable.ImportRow(DataRow)。这个方法。