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中的列顺对应
 
        }


//已存在DataTable
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.Rows.Remove(DataRow)方法

dt.Rows.Remove(dt.Rows[0]);

//使用DataTable.Rows.RemoveAt(index)方法

dt.Rows.RemoveAt(0);

//使用DataRow.Delete()方法

dt.Row[0].Delete();

dt.AcceptChanges();

 

//-----区别和注意点-----

//Remove()和RemoveAt()方法是直接删除

//Delete()方法只是将该行标记为deleted,但是还存在,还可DataTable.RejectChanges()回滚,使该行取消删除。

//用Rows.Count来获取行数时,还是删除之前的行数,需要使用DataTable.AcceptChanges()方法来提交修改。

//如果要删除DataTable中的多行,应该采用倒序循环DataTable.Rows,而且不能用foreach进行循环删除,因为正序删除时索引会发生变化,程式发生异常,很难预料后果。

for (int i = dt.Rows.Count - 1; i >= 0; i--)

{

  dt.Rows.RemoveAt(i);

}

//复制表,同时复制了表结构和表中的数据

DataTable dtNew = new DataTable();

dtNew = dt.Copy();

//复制表

DataTable dtNew = dt.Copy(); //复制dt表数据结构

dtNew.Clear() //清空数据

for (int i = 0; i < dt.Rows.Count; i++)

{

  if (条件语句)

  {
     dtNew.Rows.Add(dt.Rows[i].ItemArray); //添加数据行
  }

}

//克隆表,只是复制了表结构,不包括数据

DataTable dtNew = new DataTable();

dtNew = dt.Clone();

//如果只需要某个表中的某一行

DataTable dtNew = new DataTable();

dtNew = dt.Copy();

dtNew.Rows.Clear();//清空表数据

dtNew.ImportRow(dt.Rows[0]);//这是加入的是第一行



DataTable dt = new DataTable();//创建表

dt.Columns.Add("ID", typeof(Int32));//添加列

dt.Columns.Add("Name", typeof(String));

dt.Columns.Add("Age", typeof(Int32));

dt.Rows.Add(new object[] { 1, "张三" ,20});//添加行

dt.Rows.Add(new object[] { 2, "李四" ,25});

dt.Rows.Add(new object[] { 3, "王五" ,30});

DataView dv = dt.DefaultView;//获取表视图

dv.Sort = "ID DESC";//按照ID倒序排序

dv.ToTable();//转为表

筛选DataTable数据


        
//使用select()方法,新结果保存到DataRow[] 或者另存为一个新的DataTable
public void SelectRowDataTable()
        {
            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筛选指定字段,并保存为新表。这些字段,确保dt中存在,否则会报错误
 
            DataTable dtNew = dt.DefaultView.ToTable(false, new string[] { "列名", "列名", "列名" });
        }

DataTable.Select()小详解

Select();//全部查出来   
Select(过滤条件);//根据过滤条件进行过滤,如Select("columnname1 like '%xx%'");   
Select(过滤条件,排序字段);//过滤,并排序,如Select("columnname1 like '%xx%'",columnname2); 

完成一个查询,返回一个DataTable后,很多时候都想在查询结果中继续搜索。这时可以使用DataTable.Select方法对结果进行再查询。 
Select方法有4个重载,我们经常用到的就是DataTable.Select(String) ; 

下面就说说带一个参数的DataTable.Select(String): 
这个String的参数是查询的限定式。相当于SQL查询语言中的WHERE语句(不含WHERE),其语法符合SQL语言语法。 (网友的说法)我觉得就是类似sql的语法而已。 

但是不支持BETWEEN AND,举个成功的例子: 

//FromTime 和ToTime 是两个DateTime类型的变量;occurTime是dTable里面的列名; 

DataRow[] datarows = dTable.Select("occurTime >= '" + FromTime + "' and occurTime <= '" + ToTime+"'"); 

DataTable.Select()方法里面支持简单的过滤和排序,不支持复杂的条件过滤和排序。里面的字符串必须是列名和数据,以及>,<,=,<>等关系运算符。举几个例子: 

DataRow[] row = Detailtb.Select("WZMC='"+MaterialName+"' and CZ='"+MaterialTexture+" and   GG='"+MaterialSpecs+"'");    

DataTable.Select("City Like 'B%'"); 

DataTable.Select("name='" + a +"'"); 

下面这条语句选择Pubdate字段日期在2000年1月1日当天或之后的DataRow 

DataRow[] arrRows = table.Select("pubdate>='#1/1/2000#'");

操作符可以被支持:<,<=,=,>=,>和<>也可以使用IN和Like

返回"state"等于CA、TN或WA的所有行

DataRow[] arrRows = table.Select("state in('ca','tn','wa')");

返回"state"以CA开头的所有行

DataRow[] arrRows = table.Select("state like 'ca*'");
            
还可以使用一些Sql函数,在DataTable中选择State字段为空的记录

DataRow[] arrRows = table.Select("isnull(state,0)=0");

还可以使用And、Or和Not
            
DataRow[] arrRows = table.Select("state='tn' and zip like '37*'");
/*总之,可以用括号分组,创建复杂的布尔表达式*/

一定要注意单引号的问题,要先有双引号,再用单引号;即‘“变量”’; 

排序

//建议在查询的时候就排序
//这是在数据已经出来后的排序
//方法一
public DataTable LinqSortDataTable(DataTable tmpDt)
        {
            DataTable dtsort = tmpDt.Clone();
            dtsort = tmpDt.Rows.Cast<DataRow>().OrderBy(r =>r["villagecode"].ToDecimal()).CopyToDataTable();
            return dtsort;
        }
        
//方法二
public DataTable LinqSortDataTable(DataTable tmpDt)
        {
            int sortId = 3
            DataView dv = tmpDt.DefaultView;
            var query = (from item in tmpDt.AsEnumerable()
                         orderby (item[sortId].ToDecimal())
                         select item);
            dv = query.AsDataView();
            return  dv.ToTable();
        }
//方法三
public DataTable LinqSortDataTable(DataTable tmpDt)
        { 
            dtTemplate.DefaultView.Sort = " villagecode asc ";
    		dtTemplate.DefaultView.RowFilter = "NAME = '张三'";
            return  dtTemplate.DefaultView.ToTable();
        }

分组

//方式一 使用数据字典
public Dictionary<string, DataTable> Grouping(DataTable table){
    
    Dictionary<string, DataTable> dict = new Dictionary<string, DataTable>();
    DataView dv = new DataView(table);
    //去重并取得列名为NAME的所有数据
    DataTable dtTJ = dv.ToTable(true, "NAME");
    for (int i = 0; i < dtTJ.Rows.Count; i++)
    	{
         var res = data.Select("NAME = '" + dtTJ.Rows[i]["NAME"].ToString() + "'");//按条件查询出符合条件的行
         DataTable resDt = data.Clone();//克隆一个壳子
         foreach (var j in res)
         	{
            	resDt.ImportRow(j);//将符合条件的行放进壳子里
            }
         dict.Add(dtTJ.Rows[i]["NAME"].ToString(), resDt);//将键值对存起来
        }
    return dict;
}

//方式二 DataTable.Rows.Cast<DataRow>()

IEnumerable<IGrouping<string, DataRow>> result = dt.Rows.Cast<DataRow>()
    .GroupBy<DataRow, string>(dr => dr["A"].ToString());//按A分组
    foreach (IGrouping<string, DataRow> item in result)
    {
    }

//方式三 使用linq to DataTable group by实现
var query = from t in dt.AsEnumerable()
            group t by new { t1 = t.Field<string>("name"), t2 = t.Field<string>("sex") } into m
            select new
            {
                name = m.Key.t1,
                sex = m.Key.t2,
                score = m.Sum(n => n.Field<decimal>("score"))
            };
if (query.ToList().Count > 0)
{
    query.ToList().ForEach(q =>
    {
        Console.WriteLine(q.name + "," + q.sex + "," + q.score);
    });
}

DataTable dtGroupBy = dataTable.DataTables.AsEnumerable()
    .GroupBy(r => new { Name = r["NAME"], Times = r["Times"] }).Select(
                     g =>
                     {
                         var row = dataTable.DataTables.NewRow();

                         row["NAME"] = g.Key.Name;
                         row["Times"] = g.Key.Times;
                         row["Age"] = g.Sum(r => decimal.Parse(r["Age"].ToString()));
                         return row;
                     }).CopyToDataTable();
var dt = dtGroupBy.DefaultView.ToTable(true, new string[] { "NAME", "Times" });

//分组统计按次数排序
Dictionary<string, string> dicProjectExpectFiveParam = listProject.GroupBy(
    x => new { x.LHCodeID, x.ParamName })
   .Where(p => !sFiveParam.Contains(p.Key.LHCodeID))
   .Select(group => new { group.Key, LHCodeIDCount = group.Count() })
   .OrderByDescending(t => t.LHCodeIDCount)
   .ToDictionary(o => o.Key.LHCodeID, p => p.Key.ParamName);

尾语: DataTable中AsEnumerable与Cast类似,都可转为Linq统计、排序等;

分页

//运用Linq将DataTable转换为集合进行分页(拆分Table)
int PageSize = 65536;
int totalCount = Convert.ToInt32(dtDataAll.Rows.Count);
int totalPage = Convert.ToInt32(Math.Ceiling((double)totalCount / PageSize));
var dtDataAllTemp = dtDataAll.AsEnumerable();
for (var i = 0; i<totalPage; i++)
{
    DataTable dtNew = dtDataAllTemp.Skip(i * PageSize).Take(PageSize).CopyToDataTable();
}

去重

IEnumerable <DataRow> r = tbl.AsEnumerable().Distinct(new CityComparer()); 
class CityComparer : IEqualityComparer <DataRow> 
    { 
        public bool Equals(DataRow r1, DataRow r2) 
        { 
            return r1["City"] == r2["City"]; 
        } 

        public int GetHashCode(DataRow obj) 
        { 
            return obj.ToString().GetHashCode(); 
        } 
    } 

穿插一下LinqDynamic

//调用AsQueryable()方法
static void Main(string[] args)
        {
            List<Phone> PhoneLists = new List<Phone>()
            {
                new Phone { Country = "中国", City = "北京", Name = "小米" },
                new Phone { Country = "中国",City = "北京",Name = "华为"},
                new Phone { Country = "中国",City = "北京",Name = "联想"},
                new Phone { Country = "中国",City = "台北",Name = "魅族"},
                new Phone { Country = "日本",City = "东京",Name = "索尼"},
                new Phone { Country = "日本",City = "大阪",Name = "夏普"},
                new Phone { Country = "日本",City = "东京",Name = "松下"},
                new Phone { Country = "美国",City = "加州",Name = "苹果"},
                new Phone { Country = "美国",City = "华盛顿",Name = "三星"},
                new Phone { Country = "美国",City = "华盛顿",Name = "HTC"}
 
            };
            var Lists = PhoneLists.AsQueryable().Where("Country = @0 And City = @1", "中国", "北京").OrderBy("Name,City").Select("new (Country as  Country,City as City,Name as Name)");
            var dLists = Lists.ToDynamicList();
            foreach (var list in dLists)
            {
                Console.WriteLine(list.Country + "-" + list.City + "-" + list.Name);
            }
            Console.Read();
       }

//group by
static void Main(string[] args)
        {
            List<Phone> PhoneLists = new List<Phone>()
            {
                new Phone { Country = "中国", City = "北京", Name = "小米" },
                new Phone { Country = "中国",City = "北京",Name = "华为"},
                new Phone { Country = "中国",City = "北京",Name = "联想"},
                new Phone { Country = "中国",City = "台北",Name = "魅族"},
                new Phone { Country = "日本",City = "东京",Name = "索尼"},
                new Phone { Country = "日本",City = "大阪",Name = "夏普"},
                new Phone { Country = "日本",City = "东京",Name = "松下"},
                new Phone { Country = "美国",City = "加州",Name = "苹果"},
                new Phone { Country = "美国",City = "华盛顿",Name = "三星"},
                new Phone { Country = "美国",City = "华盛顿",Name = "HTC"}
 
            };
            var Lists = PhoneLists.AsQueryable().GroupBy("new (Country as Country,City as City)");
            var dLists = Lists.ToDynamicList();
            foreach (var list in dLists)
            {
                Console.WriteLine(list + ":");
                foreach (var lis in list)
                {
                    Console.WriteLine(lis.Country + "-" + lis.City + "-" + lis.Name);
                    Console.WriteLine($"{lis.Country} - {lis.City} - {lis.Name}");
                }
            }
            Console.Read();
       }
利用反射 建立模糊查询通用工具类
public static IQueryable<T> TextFilter<T>(IQueryable<T> source, T param)
        {
            // 如果参数为空
            if (param == null) { return source; }
            // 获取对象参数
            Type elementType = typeof(T);
            // 在这个类型参数中获取所有的string类型
            // Get all the string properties on this specific type.
            PropertyInfo[] stringProperties =
                elementType.GetProperties()
                    .Where(x => x.PropertyType == typeof(string))
                    .ToArray();
            // 数组是否包含任何元素
            if (!stringProperties.Any()) { return source; }
            // Get the right overload of String.Contains
            // 创建 String 方法中的 Contains 重载
            MethodInfo containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
            // Create a parameter for the expression tree:
            // the 'x' in 'x => x.PropertyName.Contains("term")'
            // The type of this parameter is the query's element type
            // 这是 Linq 表达式中的 x   the 'x' in 'x => x.PropertyName.Contains("term")'
            ParameterExpression prm = Expression.Parameter(elementType);

            List<Expression> list = new List<Expression>();
            // 遍历每个string类型
            foreach (PropertyInfo prp in stringProperties)
            {
                // 获取string类型的值
                String propertyValue = (String)prp.GetValue(param);
                // 如果是空,或者是null,不做处理
                if (String.IsNullOrEmpty(propertyValue))
                {
                    continue;
                }
                // 定义表达式
                var expression = Expression.Call(                  // .Contains(...) 
                    Expression.Property(                           // .PropertyName
                        prm,                                       // x 
                        prp
                    ),
                    containsMethod,
                    Expression.Constant(propertyValue)     // "term" 
                );
                list.Add(expression);
            }
            var expressions = list as IEnumerable<Expression>;
            // Combine all the resultant expression nodes using ||
            Expression body = expressions
                .Aggregate(
                    (prev, current) => Expression.And(prev, current)
                );

            // Wrap the expression body in a compile-time-typed lambda expression
            Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(body, prm);

            // Because the lambda is compile-time-typed (albeit with a generic parameter), we can use it with the Where method
            return source.Where(lambda);
        }

public void TEST(){
    List<Person> src = new List<Person>() { 
        new Person { LastName = "abcd", FirstName = "abcd" }, 
        new Person { LastName = "abcd", FirstName = "a" }, 
        new Person { LastName = "a", FirstName = "abcd" } 
    };
    List<Car> src1 = new List<Car>() { 
        new Car { Model = "abcd" }, 
        new Car { Model = "a" }, 
        new Car { Model = "c" } 
    };
    var query1 = DynamicLinqUtils.TextFilter(
                src.AsQueryable(),
               new Person { LastName = "c", FirstName = "c" }
            )
           .Where(x => x.DateOfBirth < new DateTime(2001, 1, 1));

    var list1 = query1.ToList();
    var query2 = DynamicLinqUtils.TextFilter(
                src1.AsQueryable(),
               new Car { Model = "c" }
            );
    var list2 = query2.ToList();
}


穿插一下List分组

//List委托
List<Act_TypeListInfo> listFind = listAllTZ.FindAll(delegate( Act_TypeListInfo f)
	{
      return f.MainID == iMainId && f.KeyName == info.ColKeyName && f.CompID == iCompID);
    });

//分组遍历
List<Cart_Model> list_CartModel = new List<Cart_Model>();  
IEnumerable<IGrouping<string, Cart_Model>> query = list_CartModel.GroupBy(pet => pet.ShopId, pet => pet);  
foreach (IGrouping<string, Cart_Model> info in query)  
{  
  List<Cart_Model> sl = info.ToList<Cart_Model>();//分组后的集合                  
  //也可循环得到分组后,集合中的对象,可以用info.Key去控制  
  foreach (KqiPageSetupInfo set in sl)   
  {   
  }                  
}  

//多表分组排序统计
var temp = from ta in areaList
        join tb in StationList on ta.AreaID equals tb.AreaID
        join tc in dcMNComple on tb.MN equals tc.Key into temp1
        //orderby ta.AreaID 
        group temp1 by new { AreaName = ta.AreaName, AreaID = ta.AreaID } into temp2
           select new
           {
             AreaName = temp2.Key.AreaName,
             AreaID = temp2.Key.AreaID,
             MNCount = temp2.Count(),
             Comple = temp2.Sum(s => s.Sum(t => t.Value))
           };
//从List中查找另一个List的匹配项
var mnList = listFind.Where(d => listYQ.Select(d1 => d1.YQID).Contains(d.YQID)).ToList();
//或 (FindAll)
var mnList = listFind.Where(delegate (T_MNYQInfo f)
{
    foreach (var itemYq in listYQ)
    {
        if (f.YQID == itemYq.YQID)
        {
            return true;
        }
    }
    return false;
}).ToList();
posted @ 2022-12-23 14:58  白日梦想家_zery  阅读(114)  评论(0编辑  收藏  举报