一、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. 在eNSP上配置VLAN的Trunk端口

    1.实验内容:在不同交换机下不同部门的员工能够互相通信,需要配置交换机之间的链路,跨交换机实现VLAN间通信 2.实验拓扑图 3.实验配置 按照实验编址表编辑配置所有PC机的IP地址 编址表如下图: ...

  2. Nginx+PHP(FastCGI)高性能服务器加载redis+memcache模块

    1)Nginx+FastCGI安装配置: yum install  openssl openssl-devel pcre-devel pcre zlib zlib-devel –y #下载Nginx源 ...

  3. 【k8s第三步】Kubernetes-Dashboard仪表盘【已修正错误】

    ⒈下载描述文件 wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta6/aio/deploy/recommen ...

  4. 数据结构 -- 二叉树(Binary Search Tree)

    一.简介 在计算机科学中,二叉树是每个结点最多有两个子树的树结构.通常子树被称作“左子树”(left subtree)和“右子树”(right subtree).二叉树常被用于实现二叉查找树和二叉堆. ...

  5. Centos安装 k8s

    ### 一. 安装docker 1.安装依赖包```shellsudo yum install -y yum-utils device-mapper-persistent-data lvm2 ``` ...

  6. 网络模式: host-only & NAT & 桥接

    基本上,Host-only相当于虚拟机和宿主机通过交叉线相连:NAT,宿主机相当于虚拟机的路由器:桥接,相当于把宿主机和虚拟机同时接到交换机上,然后交换机接到外网. 连接性上说,可参考下表: 连接 宿 ...

  7. SAS学习笔记43 宏语句

    流程控制 %GOTO语句与%label语句是结合起来使用的.首先通过%label语句定义一个位置,使用%GOTO语句可直接将程序的执行位置跳到该label标记位置,达到控制程序执行顺序的目的.可实现与 ...

  8. k8s系列0--Kubernetes基础知识

    Kubernetes介绍 参考:Kubernetes核心组件解析 Pod是k8s的最小调度单元 每个pod有独立的IP,但是pod的IP是不可靠的,重新调度pod就会改变IP,service概念就是为 ...

  9. hdu 5672 尺取还是挺好用的

    先简单介绍下尺取法 http://blog.chinaunix.net/uid-24922718-id-4848418.html 尺取法就是在卡给定条件的时候 不断的改变下标 起点 终点 #inclu ...

  10. 总结一下C++与C#之间的区别

    1,C#不支持多重继承 2.在标准的C#安全代码中不支持指针类型的操作,然而,你却能在微软所谓的“非安全代码”中操作指针类型对象. 3.C#中所有对象都只能通过关键词“new”来创建,C++的“类名_ ...