news 2026/2/18 1:49:36

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/2/5 8:26:56

5-脱氧-L-阿拉伯糖—结构独特的稀有单糖,药物设计与合成化学的宝贵砌块 CAS:13039-56-0

5-脱氧-L-阿拉伯糖是一种天然存在但相对稀有的五碳脱氧单糖,其独特的L-构型与脱氧结构赋予其区别于常见D-型糖的化学与生物学特性。作为手性合成与药物化学中的高价值砌块,它正日益受到糖化学、抗感染药物研发及糖生物学研究领域的关注。化学信息化学名称…

作者头像 李华
网站建设 2026/2/13 22:43:00

2-乙酰胺基-1,3,4,6-四-O-乙酰基-2-脱氧-5-硫代-α-D-吡喃葡萄糖 —— 糖化学与药物研发的关键砌块 CAS:67561-97-1

2-乙酰胺基-1,3,4,6-四-O-乙酰基-2-脱氧-5-硫代-α-D-吡喃葡萄糖是糖化学与糖药物研究领域中一类重要的修饰单糖衍生物。作为5-硫代葡萄糖的结构前体与保护形式,它不仅是糖生物学基础研究的关键工具分子,更为开发新型糖基化抑制剂、糖模拟药物及诊断探针…

作者头像 李华
网站建设 2026/2/14 15:30:23

群体分析如何改变你的客户洞察

原文:towardsdatascience.com/how-cohort-analysis-can-transform-your-customer-insights-ff7e221b8fdc 尽管进行了数月的营销努力,但你的销售额仍在下降,客户参与度也在下降。出了什么问题?如果有一种方法可以精确地确定客户何时…

作者头像 李华
网站建设 2026/2/16 9:41:09

别再为BGM被下架了,可以生成带声音且无版权素材的AI,真的来了

我做自媒体这么多年,最怕的不是没灵感,而是“做完视频被版权一刀切”。BGM 要么平台判侵权,要么授权贵到离谱;环境音、拟音、人声配音更麻烦——自己录质量差,请配音师成本高、周期长。所以我一直在找一种东西&#xf…

作者头像 李华
网站建设 2026/2/16 19:07:32

vue和springboot框架开发的校园商店零售管理系统_pt87nuk3

文章目录具体实现截图主要技术与实现手段关于我本系统开发思路java类核心代码部分展示结论源码lw获取/同行可拿货,招校园代理 :文章底部获取博主联系方式!具体实现截图 同行可拿货,招校园代理 vuespringboot_pt87nuk3 框架开发的校园商店零售管理…

作者头像 李华
网站建设 2026/2/16 22:39:48

vue和springboot框架开发的校园智能AI问答技术的快递物流管理系统_5kf8to85

文章目录具体实现截图主要技术与实现手段关于我本系统开发思路java类核心代码部分展示结论源码lw获取/同行可拿货,招校园代理 :文章底部获取博主联系方式!具体实现截图 同行可拿货,招校园代理 vuespringbootAI_5kf8to85 问答技术的快递物流管理系…

作者头像 李华