一、DataTable的扩展方法:

1、DataTable转Linq:AsEnumerable 方法

返回的EnumerableRowCollection<DataRow> 实现了 IEnumerable<T>接口。其中泛型参数T是DataRow。

此对象可用在 LINQ表达式或方法查询中。

语法:

public static EnumerableRowCollection<DataRow> AsEnumerable (this DataTable source);

在以下示例中,一个 DataColumn 数据表ProductName,提取ProductName值,然后将值输出。

DataTable table = new DataTable();
table.Columns.Add("ID");
table.Columns.Add("ProductName"); table.Rows.Add("1", "Chai");
table.Rows.Add("2", "Queso Cabrales");
table.Rows.Add("3", "Tofu"); var productNames = from products in table.AsEnumerable()
                   select products.Field<string>("ProductName");
Console.WriteLine("Product Names: ");
foreach (string productName in productNames)
{
Console.WriteLine(productName);
}

注意:转成EnumerableRowCollection后,需要对两个这样的行集合进行操作,如:Distinct,Union,Except,Intesect,SequenceEqual都需要对数据源的元素进行相等比较,需要使用专门为Linq To Datatable新增加的DataRowComparer作为参数(实现了IEqulityComparer接口),用于比较DataRow的值(而不是引用比较)。否则,根本不能达到预期操作。

IEnumerable<DataRow> distinctTable = table.AsEnumerable().Distinct(DataRowComparer.Default);

2、Linq转DataTable

(1)返回DataTable,其中包含的副本DataRow对象。

public static DataTable CopyToDataTable<T> (this IEnumerable<T> source) where T : DataRow;

以下示例查询 SalesOrderHeader 表的订单后 2001 年 8 月 8 日,并使用CopyToDataTable方法来创建DataTable从该查询。

DataTable orders = ds.Tables["SalesOrderHeader"];

IEnumerable<DataRow> query =
from order in orders.AsEnumerable()
where order.Field<DateTime>("OrderDate") > new DateTime(2001, 8, 1)
select order; // Create a table from the query.
DataTable boundTable = query.CopyToDataTable<DataRow>();

(2)副本表的DataRow到指定的对象DataTable。

public static void CopyToDataTable<T> (this IEnumerable<T> source, DataTable table, LoadOption options) where T : DataRow;

LoadOption:当使用 LoadLoad 方法时控制数据源中的值如何应用至现有行。

  1. OverwriteChanges:    传入此行的值将同时写入每列数据的当前值和原始值版本。
  2. PreserveChanges:   传入此行的值将写入每列数据的原始值版本。 每列数据的当前版本不变化。 这是默认设置。
  3. Upsert  : 传入此行的值将写入每列数据的当前版本。 每列数据的原始版本不变化。

以下示例:如果tableold表设置了主键,则可以合并记录,否则追加。

table.AsEnumerable().CopyToDataTable(tableold,LoadOption.OverwriteChanges);

tips:默认情况下(没对表进行操作),数据行的Original版本是不存在的,视图访问将报错。可以在访问之前使用DataRow.HasVersion来判断,也可以通过调用DataRow.AcceptChanges()方法来建立Original版本,避免异常发生。

二、DataRow中的扩展方法:

(1)获取字段值

Field:提供对 DataRow 中的每个列值的强类型访问。

public static T Field<T> (this DataRow row, string columnName);

举例:

foreach (DataRow row in table.AsEnumerable())
{
row.Field<int>("Id");
row.Field<string>("Name", DataRowVersion.Original);
}

(2)设置字段值

Set​Field:为 DataRow 中的指定列设置一个新值。

public static void SetField<T> (DataRow row, string columnName, T value);

如果value是null,则SetField方法转换null值设置为DBNull.Value。

举例:

var rows = from s in table.AsEnumerable()
where s.Field<string>("Name") == "c"
select s;
rows.Single<DataRow>().SetField("Name", "cc");

三、Linq To DataTable的常见用法。

1、查询:

DataTable table = new DataTable();
table.Columns.Add("ID", Type.GetType("System.Int32"));
table.Columns.Add("PID", Type.GetType("System.Int32"));
table.Columns.Add("CreateDate", Type.GetType("System.DateTime")); table.Rows.Add(1, 2, "2010-1-1");
table.Rows.Add(2, 3, "2011-1-1");
table.Rows.Add(3, 3, "2012-1-1");
table.Rows.Add(4, 2, null); var rows = from s in table.AsEnumerable()
where s.Field<int>("ID") > 1 && !s.IsNull("CreateDate")
select new
{
ID = s["ID"],
CreateDate = s["CreateDate"]
};
rows.ToList().ForEach(m => Console.WriteLine(m.ID + "-" + m.CreateDate));//2-2011-01-01 0:00:00 3-2012-01-01 0:00:00

2、分组:

var query = from r in table.AsEnumerable()
group r by new
{
PID = r.Field<int>("PID")
} into g
select new
{
Pid = g.Key.PID,
FirstCreateDate = g.First().Field<DateTime>("CreateDate"),
IDS = string.Join(",", g.Select(n => n.Field<int>("ID")).ToArray()),
Count = g.Count(q => q.Field<int>("ID") > 1),
Sum1 = g.Sum(q => q.Field<int>("ID"))
};
query.ToList().ForEach(m => Console.WriteLine(m.Pid + "-" + m.FirstCreateDate + "-" + m.IDS));//2-2010-01-01 0:00:00-1,4 3-2011-01-01 0:00:00-2,3

例2:按PID分组,获取倒数第二条信息

var query1 = from r in table.AsEnumerable()
where new int[] { 3, 4 }.Contains(r.Field<int>("PID"))
orderby r.Field<DateTime>("CreateDate") descending
group r by r.Field<int>("PID") into g
let n = (from d in g.Take(2).Skip(1) select d).FirstOrDefault()
select new
{
PID = g.Key,
ID = n.Field<int>("ID"),
CreateDate = n.Field<DateTime>("CreateDate")
};
query1.ToList().ForEach(m => Console.WriteLine(m.PID + "-" + m.ID + "-" + m.CreateDate));//3-2-2011-01-01 0:00:00

3、Join组合查询:

var result = from t1 in table.AsEnumerable()
join t2 in table.AsEnumerable() on
t1.Field<int>("ID") equals t2.Field<int>("ID")
where t2.Field<DateTime?>("CreateDate") < DateTime.Today || !t2.Field<DateTime?>("CreateDate").HasValue
select new
{
ID = t2.Field<int>("ID"),
CreateDate = t1.Field<DateTime?>("CreateDate")
};
result.ToList().ForEach(m => Console.WriteLine(m.ID + "-" + m.CreateDate));

LINQ to DataSet,对离线数据的Linq支持、AsEnumeable()的更多相关文章

  1. LINQ系列:LINQ to DataSet的DataTable操作

    LINQ to DataSet需要使用System.Core.dll.System.Data.dll和System.Data.DataSetExtensions.dll,在项目中添加引用System. ...

  2. LINQ(LINQ to DataSet)

    http://www.cnblogs.com/SkySoot/archive/2012/08/21/2649471.html DataTable.Select()方法使用和 SQL 相似的过滤语法从 ...

  3. C#数据操作LINQ

    Linq是language integrated query的缩写,即"语言集成查询"之意. Linq主要包含四个组件,Linq to object.Linq to XML.Lin ...

  4. 泛型 Field 和 SetField 方法 (LINQ to DataSet)

    LINQ to DataSet 为 DataRow 类提供用于访问列值的扩展方法:Field 方法和 SetField 方法.这些方法使开发人员能够更轻松地访问列值,特别是 null 值.DataSe ...

  5. C# LINQ系列:LINQ to DataSet的DataTable操作 及 DataTable与Linq相互转换

    LINQ to DataSet需要使用System.Core.dll.System.Data.dll和System.Data.DataSetExtensions.dll,在项目中添加引用System. ...

  6. EntityFramework数据持久化 Linq介绍

    一.LINQ概述与查询语法 二.LINQ方法语法基础(重点) 三.LINQ聚合操作与元素操作(重点) 四.数据类型转换(重点) 一.LINQ概述与查询语法 1.LINQ(Language Integr ...

  7. EntityFramework数据持久化 Linq语法应用

    Linq基础语法 LINQ概述 LINQ(Language Integrated Query,语言集成查询)提供了一种跨数据源和数据格式查询的统一模型. LINQ的组成: LINQ To Object ...

  8. Code First开发系列之管理数据库创建,填充种子数据以及LINQ操作详解

    返回<8天掌握EF的Code First开发>总目录 本篇目录 管理数据库创建 管理数据库连接 管理数据库初始化 填充种子数据 LINQ to Entities详解 什么是LINQ to ...

  9. 8天掌握EF的Code First开发系列之3 管理数据库创建,填充种子数据以及LINQ操作详解

    本文出自8天掌握EF的Code First开发系列,经过自己的实践整理出来. 本篇目录 管理数据库创建 管理数据库连接 管理数据库初始化 填充种子数据 LINQ to Entities详解 什么是LI ...

随机推荐

  1. mysql--简单操作

    一.数据库的基本操作 查看当前所有存在的数据库 show databases; //mysql 中不区分大小写.(databank 是之前创建的) 创建数据库 create database data ...

  2. JAVA第09次实验(IO流)

    JAVA第09次实验(IO流) 0.字节流与二进制文件 我的代码 import java.io.DataInputStream; import java.io.DataOutputStream; im ...

  3. [转帖]MMU内存管理单元

    MMU内存管理单元 https://www.cnblogs.com/alantu2018/p/9002309.html 之前对这一块一直不理解 最近学习了点 CPU time slice 以及 con ...

  4. Python豆瓣源镜像

    pip install pymysql -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

  5. Java基础---Java变量

    变量:程序运行期间,内容可以发生改变的量. 创建一个变量并且使用的格式: 数据类型 变量名称;         // 创建了一个变量 变量名称 = 数据值;           // 赋值,将右边的数 ...

  6. 利用Python进行数据分析_Pandas_处理缺失数据

    申明:本系列文章是自己在学习<利用Python进行数据分析>这本书的过程中,为了方便后期自己巩固知识而整理. 1 读取excel数据 import pandas as pd import ...

  7. C 统计用户输入的总行数和字符长度

    C 统计用户输入的总行数和字符长度 #include <stdio.h> #include <Windows.h> int main(void) { ]; ; ; printf ...

  8. golang之面向对象编程

    1.Golang语言面向对象编程说明 1)Golang也支持面向对象编程(OOP),但是和传统的面向对象编程有区别,并不是纯粹的面向对象语言.所以我们说Golang支持面向对象编程特性是比较准确的. ...

  9. Redis的AOF重写脚本

    手动触发 每天定期的去执行一次 写了一个脚本 bgrewriteaof.sh 内容如下: #!/bin/bash /usr/local/redis/redis-cli -p 6379 -h 127.0 ...

  10. Apache2.4+Tomcat7.0整合配置详解

    一.简单介绍 Apache.Tomcat Apache HTTP Server(简称 Apache),是 Apache 软件基金协会的一个开放源码的网页服务器,可以在 Windows.Unix.Lin ...