一、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. go json解析Marshal和Unmarshal

    Decoder: package main import ( "encoding/json" "fmt" "io" "log&qu ...

  2. 【牛客网】Longest Common Subsequence

    [牛客网]Longest Common Subsequence 发现只有d数组最格路 于是我们把前三个数组中相同的数记成一个三维坐标,同一个数坐标不会超过8个 从前往后枚举d,每次最多只会更新不超过8 ...

  3. javaIO -- File源码

    一.简介 文件和目录路径名的抽象表示. 用户界面和操作系统使用依赖于系统的路径名字符串命名文件和目录. 这个类提供了一个抽象的,独立于系统的层次化路径名的视图. 二.代码 (一).属性详情 //平台的 ...

  4. (九)Javabean与Jsp(来自那些年的笔记)

    目录 JavaBean 在JSP中使用JavaBean 标签用法 带标签体的 JavaBean 标签 setProperty 标签 getProperty 标签 JSP开发模式 案列:使用 模式一 编 ...

  5. docker 实践四:仓库管理

    本篇我们来了解 docker 仓库的内容. 注:环境为 CentOS7,docker 19.03 仓库(Responsitory)是集中存放镜像的地方,又分公共仓库和私有仓库. 注:有时候容易把仓库与 ...

  6. qt聊天室bug-- error: no matching function for call to 'Ui::Widget::setupUi(Widget*)' ui->setupUi(this); ^

  7. dg环境连接ORA-00604,ORA-16000: database open for read-only access

    报错信息 根据客户提供的报错信息, ORA-: error occurred at recursive SQL level ORA-: database open for read-only acce ...

  8. oracle查询十分钟之前的数据

    select * from TABLE as of timestamp sysdate - 10/1440 t WHERE ColName='1111'; TABLE:表名 WHERE:查询子句 sy ...

  9. Asp.Net Core 轻松学系列-1阅读指引目录

    https://www.cnblogs.com/viter/p/10474091.html 目录 前言 1. 从安装到配置 2. 业务实现 3. 日志 4. 测试 5. 缓存使用 6.网络和通讯 7. ...

  10. [NOIP2018模拟赛10.23]发呆报告

    闲扯 考场看了眼题目感觉很难,一个小时敲完了所有暴力...嗯然后就在那里发呆什么事也没做 T3考场上把数据结构想了个遍都不会完成1操作,现在看这种思路其实之前也接触过... 比较玄学的一件事情就是T1 ...