C# DataTable.Select() 筛选数据 返回新DataRow[]
有时候我们需要对数据表进行筛选,微软为我们封装了一个公共方法,DataTable.Select(),其用法如下:
Select()
Select(string filterExpression)
Select(string filterExpression, string sort)
Select(string filterExpression,string sort, DataViewRowState record States)
1) Select()——获取所有 System.Data.DataRow 对象的数组;
2) Select(string filterExpression)——按照主键顺序(如果没有主键,则按照添加顺序)获取与筛选条件相匹配的所有 System.Data.DataRow 对象的数组;
3) Select(string filterExpression, string sort)——获取按照指定的排序顺序且与筛选条件相匹配的所有System.Data.DataRow 对象的数组;
4) Select(string filterExpression, string sort, DataViewRowState recordStates)——获取与排序顺序中的筛选器以及指定的状态相匹配的所有。
举例说明:
有一个用户表,名称为 dtUsers,有id、姓名name、性别sex、年龄age
1.筛选所有的用户
DataRow[] drs1 =dtUsers.Select();
2.筛选所有性别为男的用户
DataRow[] drs2 =dtUsers.Select("sex = '男' ");
3.筛选所有性别为男且年龄在18岁以上的用户
DataRow[] drs3 =dtUsers.Select("sex = '男' and age >= 18");
4.筛选所有性别为男或者年龄在18岁以上的用户
DataRow[] drs4 =dtUsers.Select("sex = '男' or age >= 18");
5.筛选所有姓“夏”的用户
DataRow[] drs5 =dtUsers.Select("name like '夏%'");
6.筛选所有18岁以上的用户且按从大到小的顺序排序
DataRow[] drs5 =dtUsers.Select("age >=18","age desc");
7.上面最后一种用法没试过,有机会再列举出来。
注意事项
1.上面的Select操作是不区分大小写的(表字段不敏感,如pl-sql语法),如果需要区分大小写,需要将DataTable的caseSensitive属性设为true,例如上表的
dtUsers.CaseSensitive = true;//区分大小写
C#中DataRow的初始化
那么如何初始化这一个DataRow呢?我们知道,DataRow是DataTable的组件,而且在MSDN上可以看到DataRow的构造函数是protected类型的,它只能在内部进行构造,单独的实例化,DataRow row = new DataRow ()是不允许的。那么我们要使用DataRow就有以下两种方法进行实例化。
1、已知已存在的一个DataTable的对象table,当然这个对象的结构都已经有了,如下
DataRow row=table.NewRow();
这样便实例化了一个和已知的table一样的结构的一个DataRow 对象,可以对列进行赋值操作。
2、没有已知的DataTable,但是又想按自己写的结构保存,那么,就需要先实例化一个和你的需求一样的DataTable,然后,如1进行实例化。
static DataTable dt = null;
private static DataTable Dt
{
get
{
if (dt == null)
{
dt = new DataTable();
dt.Columns.Add(列名1);
dt.Columns.Add(列名2);
dt.Columns.Add(列名3);
}
return dt;
}
}
实例化DataRow,
DataRow row=Dt.NewRow();
那么如果这个row在别的地方被引用,就可以取值
object value = row[列名1]
这样我们就可以在程序中保存一些数据,而不用再写一个Model类来保存了,避免在其他地方引用不方便。
如何给DataTable、DataRow 手动赋值
DataTable MyDataTable = new DataTable();
MyDataTable.Columns.Add(new DataColumn("学生编号", typeof(string)));
MyDataTable.Columns.Add(new DataColumn("姓名", typeof(string)));
MyDataTable.Columns.Add(new DataColumn("学校", typeof(string)));
MyDataTable.Columns.Add(new DataColumn("联系电话", typeof(string)));
MyDataTable.Columns.Add(new DataColumn("家庭住址", typeof(string)));
DataRow dr;
for (int i = 0; i <= 10; i++)
{
dr = MyDataTable.NewRow();
dr["学生编号"] = Guid.NewGuid().ToString();
dr["姓名"] = "222";
dr["学校"] = "444";
dr["联系电话"] = "555";
dr["家庭住址"] = "666";
MyDataTable.Rows.Add(dr);
}
DataRow 类
DataRow 和 DataColumn 对象是 DataTable 的主要组件。使用 DataRow 对象及其属性和方法检索、评估、插入、删除和更新DataTable 中的值。DataRowCollection 表示 DataTable 中的实际 DataRow 对象,DataColumnCollection 中包含用于描述DataTable 的架构的 DataColumn 对象。使用重载的 Item 属性返回或设置 DataColumn 的值。
使用 HasVersion 和 IsNull 属性确定特定行值的状态,使用 RowState 属性确定行相对于它的父级 DataTable 的状态。
若要创建新的 DataRow,请使用 DataTable 对象的 NewRow 方法。创建新的 DataRow 之后,请使用 Add 方法将新的 DataRow添加到 DataRowCollection 中。最后,调用 DataTable 对象的 AcceptChanges 方法以确认是否已添加。有关将数据添加到DataTable 中的更多信息,请参见 将数据添加到表中。
您可通过调用 DataRowCollection 的 Remove 方法或调用 DataRow 对象的 Delete 方法,从 DataRowCollection 中删除DataRow。Remove 方法将行从集合中移除。与此相反,Delete 标记要移除的 DataRow。在调用 AcceptChanges 方法时发生实际移除。通过调用 Delete,您可在实际删除行之前以编程方式检查哪些行被标记为移除。有关更多信息,请参见 从表中删除行。
下面的示例通过调用 DataTable 对象的 NewRow 方法创建新的 DataRow。
private void CreateNewDataRow()
{
// Use the MakeTable function below to create a new table.
DataTable table;
table = MakeNamesTable();
// Once a table has been created, use the
// NewRow to create a DataRow.
DataRow row;
row = table.NewRow();
// Then add the new row to the collection.
row["fName"] = "John";
row["lName"] = "Smith";
table.Rows.Add(row);
foreach (DataColumn column in table.Columns)
Console.WriteLine(column.ColumnName);
dataGrid1.DataSource = table;
}
private DataTable MakeNamesTable()
{
// Create a new DataTable titled 'Names.'
DataTable namesTable = new DataTable("Names");
// Add three column objects to the table.
DataColumn idColumn = new DataColumn();
idColumn.DataType = System.Type.GetType("System.Int32");
idColumn.ColumnName = "id";
idColumn.AutoIncrement = true;
namesTable.Columns.Add(idColumn);
DataColumn fNameColumn = new DataColumn();
fNameColumn.DataType = System.Type.GetType("System.String");
fNameColumn.ColumnName = "Fname";
fNameColumn.DefaultValue = "Fname";
namesTable.Columns.Add(fNameColumn);
DataColumn lNameColumn = new DataColumn();
lNameColumn.DataType = System.Type.GetType("System.String");
lNameColumn.ColumnName = "LName";
namesTable.Columns.Add(lNameColumn);
// Create an array for DataColumn objects.
DataColumn[] keys = new DataColumn[1];
keys[0] = idColumn;
namesTable.PrimaryKey = keys;
// Return the new DataTable.
return namesTable;
}
关于Datatable的一些用法
C#动态操作DataTable(新增行、列、查询行、列等)
方法一:动态创建一个DataTable ,并为其添加数据
public void CreateTable()
{
//创建表
DataTable dt = new DataTable();
//1、添加列
dt.Columns.Add("Name", typeof(string)); //数据类型为 文本
//2、通过列架构添加列
DataColumn age = new DataColumn("Age", typeof(Int32)); //数据类型为 整形
DataColumn Time = new DataColumn("Time", typeof(DateTime)); //数据类型为 时间
dt.Columns.Add(age);
dt.Columns.Add(Time);
//1、添加空行
DataRow dr1 = dt.NewRow();
dt.Rows.Add(dr1);
//2、添加空行
dt.Rows.Add();
//3、添加数据行
DataRow dr2 = dt.NewRow();
dr2[0] = "张三"; //通过索引赋值
dr2[1] = 23;
dr2["Time"] = DateTime.Now;//通过名称赋值
dt.Rows.Add(dr2);
//4、通过行框架添加
dt.Rows.Add("李四", 25, DateTime.Now);//Add你们参数的数据顺序要和dt中的列顺对应
}
方法二:为已有DateTable添加一新列,其值可设为默认值,也可设这列不可为空。
public void CreateTable(DataTable vTable)
{
//为已有DataTable添加一新列
DataColumn dc1 = new DataColumn("Tol", typeof(string));
vTable.Columns.Add(dc1);
//添加一新列,其值为默认值
DataColumn dc2 = new DataColumn("Sex", typeof(string));
dc2.DefaultValue = "男";
dc2.AllowDBNull = false;//这在初床表的时候,其作用,在为已有表新增列的时候,不起作用
vTable.Columns.Add(dc2);
}
方法三:筛选DataTable中的数据,使用 Select()方法,把赛选结果可以保存到 DataRow[] drArr; 数据里面,也可以另存为一个新DataTable
DataTable dt = new DataTable();//假设dt是由"SELECT C1,C2,C3 FROM T1"查询出来的结果
for (int i = 0; i < dt.Rows.Count; i++)
{
if (dt.Rows[i]["C1"].ToString() == "abc")//查询条件
{
//进行操作
}
}
//但这种做法用一两次还好说,用多了就累了。那有没有更好的方法呢?就是dt.Select(),上面的操作可以改成这样:
DataRow[] drArr = dt.Select("C1='abc'");//查询(如果Select内无条件,就是查询所有的数据)
//还可以这样操作:
DataRow[] drArr1 = dt.Select("C1 LIKE 'abc%'");//模糊查询(如果的多条件筛选,可以加 and 或 or )
DataRow[] drArr2 = dt.Select("'abc' LIKE C1 + '%'", "C2 DESC");//另一种模糊查询的方法
DataRow[] drArr3 = dt.Select("C1='abc'", "C2 DESC");//排序
//问题又来了,如果要把DataRow赋值给新的DataTable,怎么赋值呢?你可能会想到:
DataTable dtNew1 = dt.Clone();
for (int i = 0; i < drArr.Length; i++)
{
dtNew1.Rows.Add(drArr[i]);
}
//但这样程序就会出错,说该DataRow是属于其他DataTable的,那要怎么做呢?很简单,这样就可以解决了:
DataTable dtNew2 = dt.Clone();
for (int i = 0; i < drArr.Length; i++)
{
dtNew2.ImportRow(drArr[i]);//ImportRow 是复制
}
}
方法四:对DataTable筛选指定字段,并保存为新表
public void SelectColumnDataTable(DataTable dt)
{
//对DataTable筛选指定字段,并保存为新表
DataTable dtNew = dt.DefaultView.ToTable(false, new string[] { "列名", "列名", "列名" });//这些列名,确保dt中存在,否则会报错误
}
方法五:对DataTable进行排序设置(sort)
public void SortDataTable(DataTable dt)
{
dt.DefaultView.Sort = "id desc";//重新设置排序
DataTable dtNew = dt.DefaultView.ToTable(); //保存在一张新表中
}
方法六:对DataTable去除重复行
1 数据库直接去除重复
select distinct * from 表名
去除了重复行distinct
2 对 DataTable直接进行操作
DataTable dt=db.GetDt("select * from 表名"); //获得datatable
DataView dv = new DataView(dt); //虚拟视图吧,我这么认为
DataTable dt2 = dv.ToTable(true, "name,age,hobby");
这个时候 dt2就是去除了重复的行了
其中
dv.ToTable(true, "name,age,hobby");
第一个参数,true 去除重复,false 不去除
第二个参数, 看意思能明白,你需要显示的字段,我这里显示"name,age,hobby"
方法七:DataTable 修改列名 删除列 增加列 调整列顺序
DataTable myDt =dt;
//删除列
myDt.Columns.Remove("minArea");
myDt.Columns.Remove("maxArea");
//调整列顺序 ,列排序从0开始
myDt.Columns["num"].SetOrdinal(1);
//修改列标题名称
dt.Columns["num"].ColumnName = "搜索量";
dt.Columns["rate"].ColumnName = "百分比";
DataColumn priceColumn = new DataColumn();
//该列的数据类型
priceColumn.DataType = System.Type.GetType("System.String");
//该列得名称
priceColumn.ColumnName = "price";
//该列得默认值
priceColumn.DefaultValue ="test";
dt.Columns.Add(priceColumn);
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
#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
#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中
//将table放在视图中
DataView view = new DataView(table);
//绑定到DataGrid
dg.DataSource = view;
dg.DataBind();
#endregion
将DataTable一行放入另一个DataTable中
【概述】从一个DataTable中取一行放到另一个DataTable里报错: 该行已经属于另一个表。
第1种方法:
DataTable dt = new DataTable();
dt = ds.Tables["All"].Clone();//克隆All的结构传递给dt
DataRow[] dr = this.dataSet31.Tables["Product"].Select("bc=1"); //通过条件得到符合条件的行
for(int i=0;i<dr.Length;i++)
{
//将数组元素加入表...
dt.Rows.Add(dr[i]);//出错提示为:该行已经属于另一个表
}
// 修改后
DataTable dt = new DataTable();
dt = ds.Tables["All"].Clone();//克隆All的结构传递给dt
DataRow[] dr = this.dataSet31.Tables["Product"].Select("bc=1"); //通过条件得到符合条件的行
for(int i=0;i<dr.Length;i++)
{
//将数组元素加入表...
dt.Rows.Add(dr[i].ItemArray);
}
第2种方法:
DataTable dt1 = new DataTable();
DataTable calcdt = new DataTable();
// dt1只是获取表结构,无数据;
// calcdt 有表结构,有数据
// 原方法
foreach (DataRow dr in calcdt.Rows)
{
dt1.Rows.Add(dr);
}
// 改进后的方法
DataRow drcalc;
foreach (DataRow dr in calcdt.Rows)
{
drcalc = dt1.NewRow();
drcalc.ItemArray = dr.ItemArray;
dt1.Rows.Add(drcalc);
}