news 2026/5/8 16:21:27

c# DataSet 类

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
c# DataSet 类

在 C# 的ADO.NET体系中,DataSet是一个内存中的数据容器,可视为 “离线数据库”,用于存储和管理关系型数据(包含表、表关系、约束等),且独立于底层数据源(如 SQL Server、MySQL 等)。它是处理复杂数据关系、离线数据操作的核心组件。

一、DataSet 的核心特性

  1. 离线数据存储:数据加载后与数据源断开连接,仍可在内存中操作,适合客户端离线场景。

  2. 关系型结构:可包含多个DataTable(数据表),表之间通过DataRelation(关系)关联,支持主外键逻辑。

  3. 数据状态跟踪:自动记录数据行的修改状态(新增、修改、删除),便于批量同步回数据源。

  4. 架构独立性:自带数据架构(Schema),记录字段类型、约束(主键、唯一键等),不依赖数据源元数据。

二、DataSet 的基本结构

DataSet的结构类似小型数据库,核心组成如下:

  • Tables集合:存储多个DataTable对象(数据表),每个DataTable对应一组结构化数据。

  • Relations集合:存储DataRelation对象,定义DataTable之间的关联关系(如 “客户 - 订单” 的一对多关系)。

  • ExtendedProperties:存储自定义键值对信息(如数据集描述、创建时间等)。

三、DataSet 的常用方法与属性

方法 / 属性说明
Tables获取DataTableCollection,用于访问或管理包含的DataTable
Relations获取DataRelationCollection,用于管理表之间的关系
DataSetName获取或设置数据集名称
AcceptChanges()提交所有数据修改(将RowState重置为Unchanged
RejectChanges()撤销所有未提交的修改(恢复到上次AcceptChanges后的状态)
Merge(DataSet)将另一个DataSet的数据合并到当前数据集(常用于合并离线修改)
Clear()清空所有表中的数据(保留表结构)
GetXml()将数据集内容转换为 XML 字符串
ReadXml(string)从 XML 文件加载数据到数据集

四、使用示例:完整操作流程

以下通过 “客户 - 订单” 数据模型,展示DataSet的创建、数据操作、关系管理和持久化的完整流程。

1. 创建 DataSet 并定义表结构
// 1. 创建DataSet DataSet salesDataSet = new DataSet("SalesData"); // 数据集名称 ​ // 2. 创建客户表(Customers) DataTable customerTable = new DataTable("Customers"); // 定义列(含主键) customerTable.Columns.Add("CustomerId", typeof(int)); // 主键列 customerTable.Columns.Add("Name", typeof(string)); customerTable.Columns.Add("Phone", typeof(string)); // 设置主键 customerTable.PrimaryKey = new[] { customerTable.Columns["CustomerId"] }; ​ // 3. 创建订单表(Orders) DataTable orderTable = new DataTable("Orders"); orderTable.Columns.Add("OrderId", typeof(int)); // 主键列 orderTable.Columns.Add("CustomerId", typeof(int)); // 外键(关联Customers) orderTable.Columns.Add("Amount", typeof(decimal)); orderTable.Columns.Add("OrderDate", typeof(DateTime)); orderTable.PrimaryKey = new[] { orderTable.Columns["OrderId"] }; ​ // 4. 将表添加到DataSet salesDataSet.Tables.Add(customerTable); salesDataSet.Tables.Add(orderTable); ​ // 验证结构 Console.WriteLine($"数据集名称:{salesDataSet.DataSetName}"); Console.WriteLine($"包含表数量:{salesDataSet.Tables.Count}"); // 输出:2
2. 填充数据与操作行
// 1. 向客户表添加数据 DataTable customers = salesDataSet.Tables["Customers"]; customers.Rows.Add(1, "张三", "13800138000"); // 直接传值(按列顺序) customers.Rows.Add(2, "李四", "13900139000"); ​ // 2. 向订单表添加数据 DataTable orders = salesDataSet.Tables["Orders"]; orders.Rows.Add(1001, 1, 999.99m, new DateTime(2024, 1, 15)); // 张三的订单 orders.Rows.Add(1002, 1, 1599.50m, new DateTime(2024, 3, 20)); // 张三的订单 orders.Rows.Add(1003, 2, 599.00m, new DateTime(2024, 5, 10)); // 李四的订单 ​ // 3. 修改数据 DataRow zhangsanRow = customers.Rows.Find(1); // 通过主键查找 zhangsanRow["Phone"] = "13812345678"; // 修改手机号 ​ // 4. 删除数据 DataRow orderToDelete = orders.Rows.Find(1003); // 查找订单1003 if (orderToDelete != null) orderToDelete.Delete(); // 标记删除(未真正删除,需AcceptChanges确认) ​ // 5. 查看行状态(跟踪修改) foreach (DataRow row in customers.Rows) { Console.WriteLine($"客户ID: {row["CustomerId"]}, 状态: {row.RowState}"); } // 输出: // 客户ID: 1, 状态: Modified(已修改) // 客户ID: 2, 状态: Unchanged(未修改)
3. 定义表关系与数据导航

通过DataRelation建立表之间的关联,实现父子数据的快速导航。

// 1. 创建“客户-订单”关系(一对多) DataRelation customerOrderRel = new DataRelation( "FK_Customer_Order", // 关系名称 salesDataSet.Tables["Customers"].Columns["CustomerId"], // 父表主键 salesDataSet.Tables["Orders"].Columns["CustomerId"] // 子表外键 ); // 添加关系到DataSet salesDataSet.Relations.Add(customerOrderRel); ​ // 2. 通过父行查找子行(查询张三的所有订单) DataRow zhangsan = customers.Rows.Find(1); if (zhangsan != null) { // 获取张三的所有订单(子行) DataRow[] zhangsanOrders = zhangsan.GetChildRows(customerOrderRel); Console.WriteLine($"客户 {zhangsan["Name"]} 的订单数量:{zhangsanOrders.Length}"); foreach (DataRow order in zhangsanOrders) { Console.WriteLine($"订单ID:{order["OrderId"]},金额:{order["Amount"]}"); } } ​ // 3. 通过子行查找父行(查询订单1001的客户) DataRow order1001 = orders.Rows.Find(1001); if (order1001 != null) { DataRow customer = order1001.GetParentRow(customerOrderRel); Console.WriteLine($"订单1001的客户:{customer["Name"]}"); // 输出:张三 }
4. 数据持久化(XML 导入 / 导出)

DataSet支持直接与 XML 互转,方便数据持久化或传输。

// 1. 将数据导出为XML(含结构和数据) string xmlData = salesDataSet.GetXml(); Console.WriteLine("XML数据:"); Console.WriteLine(xmlData); ​ // 2. 保存到XML文件 salesDataSet.WriteXml("SalesData.xml"); // 仅数据 salesDataSet.WriteXmlSchema("SalesDataSchema.xml"); // 仅结构(Schema) ​ // 3. 从XML文件加载数据 DataSet newDataSet = new DataSet(); newDataSet.ReadXml("SalesData.xml"); newDataSet.ReadXmlSchema("SalesDataSchema.xml"); // 加载结构确保类型正确 Console.WriteLine($"从XML加载的客户表行数:{newDataSet.Tables["Customers"].Rows.Count}");
5. 与数据库同步(结合 DataAdapter)

DataSet的修改可通过DataAdapter批量更新回数据源,利用其状态跟踪功能自动生成增删改命令。

string connectionString = "Server=.;Database=SalesDB;Integrated Security=True;"; ​ // 1. 创建DataAdapter(作为DataSet与数据库的桥梁) using (SqlDataAdapter adapter = new SqlDataAdapter()) { // 设置查询命令(用于从数据库加载数据) adapter.SelectCommand = new SqlCommand( "SELECT CustomerId, Name, Phone FROM Customers", new SqlConnection(connectionString) ); ​ // 自动生成增删改命令(需引用System.Data.SqlClient) SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(adapter); ​ // 2. 从数据库填充DataSet DataSet dbDataSet = new DataSet(); adapter.Fill(dbDataSet, "Customers"); // 填充到"Customers"表 ​ // 3. 在内存中修改数据(模拟用户操作) DataTable dbCustomers = dbDataSet.Tables["Customers"]; dbCustomers.Rows[0]["Phone"] = "13888888888"; // 修改 dbCustomers.Rows.Add(3, "王五", "13700137000"); // 新增 dbCustomers.Rows[1].Delete(); // 删除 ​ // 4. 将修改同步回数据库(根据RowState自动执行对应SQL) int updatedRows = adapter.Update(dbDataSet, "Customers"); Console.WriteLine($"成功同步 {updatedRows} 条修改到数据库"); }

五、DataSet 的适用场景与局限性

适用场景:
  • 离线数据处理:客户端需在无网络环境下操作数据(如移动应用)。

  • 复杂数据关系:需维护多表关联(如订单 - 订单明细 - 客户),并频繁导航数据。

  • 批量数据更新:需一次性提交多条增删改操作,减少数据库交互次数。

  • 数据缓存:重复使用的数据集可缓存到内存,提升性能。

局限性:
  • 内存占用高:数据全部加载到内存,不适合处理百万级以上大数据。

  • 数据一致性风险:离线操作可能导致与数据源数据冲突(需额外处理并发)。

  • 性能开销:相比DataReader(流式读取),初始化和序列化DataSet的开销更大。

六、总结

DataSet是 C# 中处理关系型数据的强大工具,其核心价值在于离线数据管理复杂关系维护。通过与DataTableDataRelationDataAdapter等类配合,可构建完整的内存数据模型,灵活支持从数据加载、修改到同步的全流程。在实际开发中,需根据数据量和业务场景选择使用(小批量、多关系数据优先,超大数据量建议用DataReader)。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/3 9:47:34

技术演进中的开发沉思-259 Ajax:浏览器历史管理

AJAX 的出现,让前端从 “整页刷新” 迈入 “无刷新交互” 的新时代 —— 表单提交不跳转、列表翻页不卡顿、内容加载无缝衔接。但这份流畅的体验背后,却藏着一个致命的缺陷:浏览器的后退按钮失效、书签无法保存 AJAX 状态。用户点击后退&…

作者头像 李华
网站建设 2026/5/8 9:29:49

20、Linux文件处理与正则表达式实用指南

Linux文件处理与正则表达式实用指南 1. 文件压缩与解压缩工具 在Linux和类Unix系统中, zip 和 unzip 是常用的文件压缩与解压缩工具。不过,它们不能像 tar 那样组合使用进行网络文件复制。但 zip 可以接受标准输入,因此可用于压缩其他程序的输出。 例如,将 ls …

作者头像 李华
网站建设 2026/5/8 9:30:39

25、Linux文本格式化与打印全解析

Linux文本格式化与打印全解析 1. 文本格式化基础 在Linux系统中,文本的格式化和处理是非常重要的操作。 printf 命令可以实现基本的文本格式化。例如: [me@linuxbox ~]$ printf "Line: %05d %15.3f Result: %+15d\n" 1071 3.14156295 32589 Line: 01071 …

作者头像 李华
网站建设 2026/5/8 9:30:33

RAG信息检索基准评测指标的分析和探索

这里从多个角度分析和探索RAG信息检索常用的基准和评测指标。 1 BEIR 1.1 通用检索基准 (BEIR) BEIR是一个用于零样本文本信息检索的标准评估基准。它旨在解决传统模型在单一数据集上评估、难以衡量其真实泛化能力的问题,BEIR集合了18个来自不同任务和领域的公开数…

作者头像 李华
网站建设 2026/5/8 9:29:26

python-uniapp微信小程序的农产品质量追溯系统_gkm0juhi

文章目录系统截图项目技术简介可行性分析主要运用技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 :文章底部获取博主联系方式!系统截图 python-uniapp_gkmjuhi 微信小程序的农产品质量追溯系统 项目技术简介 Python版本&#xf…

作者头像 李华
网站建设 2026/5/8 9:30:39

知网AIGC查重90%到4%,全靠7个免费降重降Ai工具

市场上的降AI率工具良莠不齐,如何科学判断降AI率效果是很多学生、老师最关心的问题,担心降不来AI率,耽误时间还花不少钱。 本文将从以下五个维度系统,分析2025年主流的8个降AI工具,教大家如何选择适合自己的降AIGC工具…

作者头像 李华