在项目中,经常会遇到这样的问题。用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 ="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)。这个方法。