当前位置: 首页 > news >正文

C#中LINQ to DataSet操作及DataTable与LINQ相互转换

一、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:当使用 Load 或 Load 方法时控制数据源中的值如何应用至现有行。

  • OverwriteChanges:传入此行的值将同时写入每列数据的当前值和原始值版本。
  • PreserveChanges:传入此行的值将写入每列数据的原始值版本。 每列数据的当前版本不变化。 这是默认设置。
  • 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 gselect 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") descendinggroup r by r.Field<int>("PID") into glet 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() ont1.Field<int>("ID") equals t2.Field<int>("ID")where t2.Field<DateTime?>("CreateDate") < DateTime.Today || !t2.Field<DateTime?>("CreateDate").HasValueselect new{ID = t2.Field<int>("ID"),CreateDate = t1.Field<DateTime?>("CreateDate")};
result.ToList().ForEach(m => Console.WriteLine(m.ID + "-" + m.CreateDate));

http://www.dtcms.com/a/321704.html

相关文章:

  • 【问题解决】Mysql连接报错:1130-host ... is not allowed to connect to this MySql server
  • 快速入门flask应用(从入门到实战)
  • CPO-SVM分类预测+特征贡献SHAP分析,通过特征贡献分析增强模型透明度,Matlab代码实现,引入SHAP方法打破黑箱限制,提供全局及局部双重解释视角
  • Uber的MySQL实践(一)——学习笔记
  • Xiphos Q8 SDR DOCK子板 AD9361 宽带收发器的 SDR 模块。
  • 【AI论文】高效智能体:在降低成本的同时构建高效能智能体
  • latex基础
  • GPT-5 不仅是版本升级,它标志着 推理能力的商业化 和 Agent操作系统 的崛起,开启了 AI革命时代。
  • 二、RuoYi-Cloud-Plus 拉取到本地的准备和注意事项
  • wordpress的wp-config.php文件的详解
  • 虚幻GAS底层原理解剖九 (内存管理)
  • Jetpack Compose 主题系统全解析:从基础配置到动态切换
  • 商品、股指、ETF期权五档Tick分时历史行情数据解析
  • 数据库设计简述
  • Trae SOLO+ Holopix AI → “虚假广告“-鸠摩智转[特殊字符]割草小游戏
  • 【Unity3D实例-功能-跳跃】角色跳跃
  • Wan2.1-14B-T2V-FusionX-VACE本地部署教程:融合前沿技术,轻松掌握逼真物理模拟!
  • JAVA基础-NIO
  • 面向真实场景的定制化图像降质模型设计方案
  • 荣耀秋招启动
  • python---函数嵌套
  • 剑指offer第2版——面试题2:实现单例
  • 零知开源——基于STM32F103RBT6的TDS水质监测仪数据校准和ST7789显示实战教程
  • Windows ASLR 地址空间布局随机化技术详解
  • 连锁店管理系统的库存跟踪功能:数字化转型下的零售运营核心
  • VR 设备 PCB 怎样凭借高频材料达成高速传输
  • [激光原理与应用-185]:光学器件 - BBO、LBO、CLBO晶体的全面比较
  • (1-9-2)Java 工厂模式
  • 基于AI多模态数据分析:美国劳动力市场疲软信号识别与趋势预测
  • 塑料可回收物检测数据集-10,000 张图片 智能垃圾分类系统 环保回收自动化 智慧城市环卫管理 企业环保合规检测 教育环保宣传 供应链包装优化