一、ADO.NET基础
大家都知道,程序=数据+算法,数据的来源是多种多样的,不过就目前来说,数据库是程序开发中必不可少的一部分,那么,我们算法有了,数据也有了,怎么将他们关联起来形成一个完整的程序呢?这就涉及到了数据库的操作。ADO.NET就是C#操作数据库的一种技术。PS:本文的例子全部以SQL server为标准。
1.1、ADO.NET概述
1.1.1、ADO.NET的发展历程
ADO.NET是.NET平台上的一个数据库访问组件,它是由ADO发展而来。ADO全称ActiveX Data Objects(ActiveX数据对象),于1996年由微软发布,它的作用是在ODBC和OLE DB接口之上建立统一的数据库访问编程模型。因此,作为.NET平台上的ADO,ADO.NET就是.NET平台上“标准”的数据库访问编程模型,它支持诸如SQL Server和XML等数据源以及支持OLE DB和ODBC接口的数据源,并提供一致的访问。
1.1.2、ADO.NET的基本功能和特点
1.连接数据库:ADO.NET提供用于连接数据源的组件,如Connection对象,使开发人员能够与数据库建立连接。
2.执行命令:通过Command对象,开发人员可以执行SQL命令、存储过程等数据库操作,并获取结果。
3.数据读取:DataReader对象提供高效的数据读取方式,允许开发人员从数据库中读取数据流。
4.数据处理:ADO.NET的DataSet对象提供了一个内存中的数据存储区,可以用来存储、处理和更新从数据库中检索的数据。
5.数据绑定:开发人员可以将DataSet中的数据绑定到用户界面控件上,实现数据的展示和编辑。
6.事务处理:ADO.NET支持事务处理,确保数据的一致性和完整性。
7.批量操作:通过批量操作,可以提高数据处理性能。
8.存储过程:ADO.NET允许调用存储过程,以执行复杂的数据库操作。
9.参数化查询:通过参数化查询,可以防止SQL注入攻击,提高数据安全性。
10.与XML集成:ADO.NET支持将DataSet对象转换为XML格式,或者从XML加载数据到DataSet中。
11.与LINQ集成:LINQ to DataSet允许使用LINQ查询对DataSet进行查询和操作。
12.与Entity Framework集成:通过Entity Framework,可以使用ADO.NET进行数据库操作。
1.1.3、常见的类型和方法
1.SqlConnection:用于建立与数据库的连接。
- Open():打开数据库连接。
- Close():关闭数据库连接。
2.SqlCommand:用于执行 SQL 语句或存储过程。
- ExecuteNonQuery():执行不返回结果集的 SQL 语句或存储过程。
- ExecuteScalar():执行返回单个值的 SQL 语句或存储过程。
- ExecuteReader():执行返回数据读取器的 SQL 语句或存储过程。
3.SqlDataReader:用于从数据库中读取数据。
- Read():将数据读取到下一行。
- GetString()、GetInt32()等:获取指定列的值。
4.SqlDataAdapter:用于填充 DataSet 和 DataTable。
- Fill():从数据库中填充 DataSet 或 DataTable。
5.DataSet 和 DataTable:用于存储和操作数据。
- Tables:包含多个 DataTable 的集合。
- Rows:包含多个 DataRow 的集合。
6.SqlParameter:用于向 SQL 语句或存储过程传递参数。
- AddWithValue():添加参数及其值。
1.2、.NET Framework数据提供程序
.NET Framework中的数据提供程序是一组用于与各种数据源进行交互的组件。以下是其中一些常见的.NET数据提供程序:
1.SqlClient:这是专门为Microsoft SQL Server设计的.NET数据提供程序。它提供了一个高效的方式来连接到SQL Server数据库、执行命令和读取数据。SqlClient是专有的,仅适用于Microsoft SQL Server,但它也提供了与其他数据库的互操作性。它在
using System.Data.SqlClient;
2.OleDb:这是用于连接和操作各种数据库的.NET数据提供程序。OleDb通过使用OLE DB协议来提供一种标准方式来访问各种数据源,包括关系型数据库和非关系型数据库。通过OleDb,开发者可以使用统一的接口与不同数据库交互。
using System.Data.OleDb;
3.Odbc:这是用于连接和操作符合ODBC标准的数据库的.NET数据提供程序。ODBC(开放数据库连接)是一个通用的数据库连接标准,许多数据库管理系统都支持ODBC。通过Odbc,开发者可以使用标准的ODBC连接字符串来连接各种ODBC兼容的数据库。
using System.Data.Odbc;
4.OracleClient:这是用于连接和操作Oracle数据库的.NET数据提供程序。它提供了一组Oracle特定的类和方法,使开发者能够以高效的方式与Oracle数据库进行交互。
//需要先引入相关包
using Oracle.ManagedDataAccess.Client;
5.MySql.Data:这是一个开源的.NET数据提供程序,专门用于连接和操作MySQL数据库。它提供了一个类似于SqlClient的API,使得与MySQL数据库的交互变得简单和直观。
//需要先引入相关包
using MySql.Data.MySqlClient;
1.3、连接数据库(SqlConnection)
1.首先要建立数据库和表,脚本可以参考如下
USE [master]
GO
/****** Object: Database [mydb] Script Date: 2024/1/5 10:00:23 ******/
CREATE DATABASE [mydb]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N'mydb', FILENAME = N'E:\MSSQL13.MSSQLSERVER\MSSQL\DATA\mydb.mdf' , SIZE = 8192KB , MAXSIZE = UNLIMITED, FILEGROWTH = 65536KB )
LOG ON
( NAME = N'mydb_log', FILENAME = N'E:\MSSQL13.MSSQLSERVER\MSSQL\DATA\mydb_log.ldf' , SIZE = 8192KB , MAXSIZE = 2048GB , FILEGROWTH = 65536KB )
GO
ALTER DATABASE [mydb] SET COMPATIBILITY_LEVEL = 130
GO
IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled'))
begin
EXEC [mydb].[dbo].[sp_fulltext_database] @action = 'enable'
end
GO
ALTER DATABASE [mydb] SET ANSI_NULL_DEFAULT OFF
GO
ALTER DATABASE [mydb] SET ANSI_NULLS OFF
GO
ALTER DATABASE [mydb] SET ANSI_PADDING OFF
GO
ALTER DATABASE [mydb] SET ANSI_WARNINGS OFF
GO
ALTER DATABASE [mydb] SET ARITHABORT OFF
GO
ALTER DATABASE [mydb] SET AUTO_CLOSE OFF
GO
ALTER DATABASE [mydb] SET AUTO_SHRINK OFF
GO
ALTER DATABASE [mydb] SET AUTO_UPDATE_STATISTICS ON
GO
ALTER DATABASE [mydb] SET CURSOR_CLOSE_ON_COMMIT OFF
GO
ALTER DATABASE [mydb] SET CURSOR_DEFAULT GLOBAL
GO
ALTER DATABASE [mydb] SET CONCAT_NULL_YIELDS_NULL OFF
GO
ALTER DATABASE [mydb] SET NUMERIC_ROUNDABORT OFF
GO
ALTER DATABASE [mydb] SET QUOTED_IDENTIFIER OFF
GO
ALTER DATABASE [mydb] SET RECURSIVE_TRIGGERS OFF
GO
ALTER DATABASE [mydb] SET DISABLE_BROKER
GO
ALTER DATABASE [mydb] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
GO
ALTER DATABASE [mydb] SET DATE_CORRELATION_OPTIMIZATION OFF
GO
ALTER DATABASE [mydb] SET TRUSTWORTHY OFF
GO
ALTER DATABASE [mydb] SET ALLOW_SNAPSHOT_ISOLATION OFF
GO
ALTER DATABASE [mydb] SET PARAMETERIZATION SIMPLE
GO
ALTER DATABASE [mydb] SET READ_COMMITTED_SNAPSHOT OFF
GO
ALTER DATABASE [mydb] SET HONOR_BROKER_PRIORITY OFF
GO
ALTER DATABASE [mydb] SET RECOVERY FULL
GO
ALTER DATABASE [mydb] SET MULTI_USER
GO
ALTER DATABASE [mydb] SET PAGE_VERIFY CHECKSUM
GO
ALTER DATABASE [mydb] SET DB_CHAINING OFF
GO
ALTER DATABASE [mydb] SET FILESTREAM( NON_TRANSACTED_ACCESS = OFF )
GO
ALTER DATABASE [mydb] SET TARGET_RECOVERY_TIME = 60 SECONDS
GO
ALTER DATABASE [mydb] SET DELAYED_DURABILITY = DISABLED
GO
EXEC sys.sp_db_vardecimal_storage_format N'mydb', N'ON'
GO
ALTER DATABASE [mydb] SET QUERY_STORE = OFF
GO
USE [mydb]
GO
ALTER DATABASE SCOPED CONFIGURATION SET LEGACY_CARDINALITY_ESTIMATION = OFF;
GO
ALTER DATABASE SCOPED CONFIGURATION SET MAXDOP = 0;
GO
ALTER DATABASE SCOPED CONFIGURATION SET PARAMETER_SNIFFING = ON;
GO
ALTER DATABASE SCOPED CONFIGURATION SET QUERY_OPTIMIZER_HOTFIXES = OFF;
GO
USE [mydb]
GO
/****** Object: Table [dbo].[Course] Script Date: 2024/1/5 10:00:23 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Course](
[cid] [nchar](10) NOT NULL,
[cname] [nchar](10) NULL,
CONSTRAINT [PK_Course] PRIMARY KEY CLUSTERED
(
[cid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[Grades] Script Date: 2024/1/5 10:00:23 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Grades](
[gid] [nchar](10) NOT NULL,
[sid] [nchar](10) NULL,
[cid] [nchar](10) NULL,
[scores] [nchar](10) NULL,
CONSTRAINT [PK_Grades] PRIMARY KEY CLUSTERED
(
[gid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[Student] Script Date: 2024/1/5 10:00:23 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Student](
[sid] [nchar](10) NOT NULL,
[sname] [nchar](10) NULL,
[sex] [nchar](10) NULL,
[age] [nchar](10) NULL,
CONSTRAINT [PK_Student] PRIMARY KEY CLUSTERED
(
[sid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
USE [master]
GO
ALTER DATABASE [mydb] SET READ_WRITE
GO
2.使用SqlConnection
对象与SQL Server数据库建立连接
using System;
using System.Data.SqlClient;
namespace ADO.NET
{
internal class Program
{
static void Main(string[] args)
{
//创建数据库连接字符串
string str = "Data Source=服务器地址;Initial Catalog=mydb;User ID=sa;Password=123";//常规连接字符串
//string str = "Data Source=服务器地址;Initial Catalog=数据库名;Integrated Security=True";//使用集成安全性
//string connectionString = "Data Source=服务器地址;Initial Catalog=数据库名;User ID=用户名;Password=密码;Min Pool Size=5;Max Pool Size=100;";//使用连接池
//创建SqlConnection对象,并传入数据库的连接字符串
try
{
using (SqlConnection conn = new SqlConnection(str))
{
conn.Open();
Console.WriteLine("数据库连接成功!");
}
}
catch (Exception ex)
{
Console.WriteLine("数据库连接失败!"+ex.Message);
}
Console.ReadKey();
}
}
}
//这是oracle的连接字符串格式
//Oracle简易连接:
string str="Data Source=orclsid_127.0.0.1;User Id=用户名;Password=密码;";
//这个数据源是从Oracle的安装目录下tnsnames.ora文件中去找的。而并非是在系统的“管理工具”下的“数据源(ODBC)”中找。这个tnsnames.ora文件是在Oracle的安装目录下的“client_1/network/admin/”下。
//Oracle自定义连接:
string str="Server=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=服务器地址)(PORT=端口号)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=数据库名称)));User Id=用户名;Password=密码;Persist Security Info=True;Enlist=true;Max Pool Size=300;Min Pool Size=0;Connection Lifetime=300;";
1.4、执行命令(SqlCommand)
1.4.1、插入数据
try
{
using (SqlConnection conn = new SqlConnection(str))
{
conn.Open();
string sql = "INSERT INTO Student (sid, sname, sex, age) VALUES (@Sid, @Sname, @Sex, @Age)";
using (SqlCommand command = new SqlCommand(sql, conn))
{
//使用参数防止sql注入
command.Parameters.AddWithValue("@Sid", "0002");
command.Parameters.AddWithValue("@Sname", "小红");
command.Parameters.AddWithValue("@Sex", "男");
command.Parameters.AddWithValue("@Age", "18岁");
command.ExecuteNonQuery();
}
}
Console.WriteLine("数据插入成功!");
}
catch (Exception ex)
{
Console.WriteLine("数据插入失败!"+ex.Message);
}
Console.ReadKey();
1.4.2、更新数据
try
{
using (SqlConnection conn = new SqlConnection(str))
{
conn.Open();
string sql = "UPDATE Student SET sname = @Sname WHERE sid='0002'";
using (SqlCommand command = new SqlCommand(sql, conn))
{
command.Parameters.AddWithValue("@Sname", "小黄");
command.ExecuteNonQuery();
}
}
Console.WriteLine("数据更新成功!");
}
catch (Exception ex)
{
Console.WriteLine("数据更新失败!"+ex.Message);
}
Console.ReadKey();
1.4.3、查询数据
try
{
using (SqlConnection conn = new SqlConnection(str))
{
conn.Open();
string sql = "SELECT * FROM Student";
using (SqlCommand command = new SqlCommand(sql, conn))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine($"{reader["sid"]} {reader["sname"]} {reader["sex"]} {reader["age"]}");
}
}
}
}
Console.WriteLine("数据查询成功!");
}
catch (Exception ex)
{
Console.WriteLine("数据查询失败!"+ex.Message);
}
Console.ReadKey();
1.4.4、删除数据
try
{
using (SqlConnection conn = new SqlConnection(str))
{
conn.Open();
string sql = "DELETE FROM Student WHERE sid='0002'";
using (SqlCommand command = new SqlCommand(sql, conn))
{
command.ExecuteNonQuery();
}
}
Console.WriteLine("数据删除成功!");
}
catch (Exception ex)
{
Console.WriteLine("数据删除失败!"+ex.Message);
}
Console.ReadKey();
1.5、数据读取(SqlDataReader)
try
{
using (SqlConnection conn = new SqlConnection(str))
{
conn.Open();
string sql = "SELECT * FROM Student";
using (SqlCommand command = new SqlCommand(sql, conn))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine($"{reader["sid"]} {reader["sname"]} {reader["sex"]} {reader["age"]}");
}
}
}
}
Console.WriteLine("数据查询成功!");
}
catch (Exception ex)
{
Console.WriteLine("数据查询失败!"+ex.Message);
}
Console.ReadKey();
二、数据处理
2.1、DataSet
DataSet
是一个数据表的集合,它可以独立于任何数据源存在。它提供了对数据的内存中表示,可以与XML数据集成,并且可以同步到数据源。
2.2、DataTable
DataTable
是 DataSet
中的一个表格型数据结构,代表一个内存中的数据表。它包含了一组 DataRow
对象,这些对象代表表中的行。你可以将 DataTable
当作一个普通的二维表格看待,其中行表示记录,列表示字段。
2.3、DataColumn
DataColumn
对象定义了 DataTable
中的一列。它包含了列的名称、数据类型以及其他属性。你可以通过 DataColumn
对象设置列的默认值、是否可空、是否唯一等属性。
2.4、DataRow
DataRow
对象代表 DataTable
中的一行。你可以通过它来访问或修改这一行的数据。例如,你可以使用 DataRow
对象的索引器来访问特定列的值,或者使用 ItemArray
属性来获取或设置整行的值。
try
{
using (SqlConnection conn = new SqlConnection(str))
{
conn.Open();
string sql = "SELECT * FROM Student";
DataSet ds = new DataSet();
SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sql,conn);
sqlDataAdapter.Fill(ds);
DataTable dt = ds.Tables[0];
DataColumn col = dt.Columns[0];
DataRow dr = dt.Rows[0];
Console.WriteLine($"DataSet对象中第一个表第一行第一列的数据为:" +ds.Tables[0].Rows[0][0]);
col.ColumnName = "sname1";
Console.WriteLine($"DataTable对象中第一行第一列的数据为:" + dt.Rows[0][0]);
Console.WriteLine($"DataColumn对象中第一行的数据为:{col.ColumnName}");
Console.WriteLine($"DataRow对象中第一行的数据为:{dr[0]}");
}
}
catch (Exception ex)
{
Console.WriteLine("出现错误!"+ex.Message);
}
Console.ReadKey();
2.6、数据绑定
将DataSet中的数据绑定到UI控件上,实现数据的展示和编辑。(后期写到winform开发会详细写)
三、高级特性
3.1、事务处理
在ADO.NET中使用事务的方法,确保数据的一致性和完整性。
try
{
using (SqlConnection conn = new SqlConnection(str))
{
conn.Open();
SqlTransaction transaction = null;
try
{
// 开始事务
transaction = conn.BeginTransaction("SampleTransaction");
// 创建命令对象并关联事务
using (SqlCommand command = conn.CreateCommand())
{
command.Transaction = transaction;
command.CommandText = "INSERT INTO Student (sid, sname, sex, age) VALUES ('0009', '兔子', '男', '60岁')"; // 示例INSERT语句
command.ExecuteNonQuery(); // 执行命令
}
// 如果这里没有发生异常,则提交事务
transaction.Commit(); // 提交事务使更改生效到数据库中
Console.WriteLine("事务提交成功!");
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
if (transaction != null) // 如果存在事务,则回滚更改
{
transaction.Rollback(); // 回滚事务撤销所有更改
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("出现错误!" + ex.Message);
}
Console.ReadKey();
3.2、批量操作
高效地执行批量数据操作,提高数据处理性能。
1.使用参数化查询
- 参数化查询可以减少SQL注入的风险,同时也能提高执行效率,因为SQL Server可以重用预编译的命令和参数。
2.使用事务
- 如果需要一次性插入、更新或删除大量数据,使用事务可以确保数据的完整性和性能。事务会将所有操作包含在一个单独的数据库操作中,从而提高效率。
3.批量操作
- 对于大量数据的插入、更新或删除,考虑使用SQL Server的批量操作功能,如BULK INSERT、bcp实用程序或SQL Server Integration Services (SSIS)。这些工具专为大量数据操作而设计,通常比使用常规的SQL语句更快。
4.减少往返次数
- 如果可能,尽量在一次往返中发送多个命令。通过减少网络往返次数,您可以提高性能。
5.异步操作
- 使用
BeginExecuteNonQuery
和EndExecuteNonQuery
方法执行异步SQL命令,这样可以避免UI线程阻塞,提高应用程序响应性。
6.优化数据库设计
- 确保数据库表有适当的索引,以加速查询速度。避免不必要的JOIN操作,尽量使用合适的数据类型。
7.使用DataReader
- 使用
DataReader
而不是DataSet
来读取数据,尤其是在需要大量数据时,因为DataReader
提供更直接的数据流,避免了额外的内存分配和垃圾回收开销。
8.优化连接池
- 配置和优化SQL Server的连接池设置,确保连接得到重用而不是频繁地建立和关闭。使用连接池可以显著提高应用程序的性能。
9.使用适当的缓存策略
- 根据情况使用查询结果缓存和数据缓存。缓存可以减少对数据库的频繁访问,从而提高性能。但要确保适当地管理和过期缓存数据,以避免数据不一致性。
10.监控和调优
- 使用SQL Server Profiler和Performance Monitor等工具监控数据库性能。基于这些数据,调整查询、索引和其他相关设置来优化性能。
11.考虑使用Entity Framework或Dapper等ORM工具
- 对于复杂的对象关系映射需求,Entity Framework或Dapper等ORM工具可能提供更高级别的抽象和性能优化功能。它们通常具有内建的批量操作支持。
12.避免频繁的数据库交互
- 如果可能,尽量减少与数据库的交互次数。例如,通过批量处理和批处理提交来减少网络往返次数。
13.升级硬件和网络
- 在某些情况下,数据库操作的性能瓶颈可能不是由于代码或查询设计不当,而是由于硬件限制或网络延迟。考虑升级硬件或改善网络连接,特别是对于高负载的应用程序。
3.3、存储过程
存储过程(Stored Procedure)是一种在数据库中存储复杂程序,用户通过调用存储过程来执行这个程序。存储过程可以是一条或多条SQL语句的集合。通过调用存储过程,用户可以执行一系列操作,而无需编写多条SQL语句。简单来说,存储过程就是一条或多条SQL语句的集合。
下面,我们先写一个简单的存储过程
go
create procedure usp_MyProcedure --创建存储过程
as
UPDATE Student SET sname = '测试' WHERE sid='0001'
go
调用这个存储过程
try
{
using (SqlConnection conn = new SqlConnection(str))
{
conn.Open();
using (SqlCommand command = new SqlCommand("usp_MyProcedure", conn)) // 指定存储过程名
{
command.CommandType = CommandType.StoredProcedure; // 指定为存储过程
try
{
// 执行存储过程,这里不需要指定参数,因为存储过程没有参数
command.ExecuteNonQuery(); // 执行更新操作
Console.WriteLine("存储过程执行成功!");
}
catch (Exception ex)
{
Console.WriteLine("发生错误: " + ex.Message);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("出现错误!" + ex.Message);
}
Console.ReadKey();
3.4、参数化查询
参数化查询是一种重要的技术,用于防止SQL注入攻击并提高查询性能。参数化查询使用参数占位符代替直接拼接SQL语句中的值,这样可以确保输入值被正确地转义,并且可以避免SQL注入的风险。其实,在上边的几个例子我们已经使用过这项技术。
try
{
using (SqlConnection conn = new SqlConnection(str))
{
conn.Open();
string sql = "SELECT * FROM Student WHERE sid=@Sid";
using (SqlCommand command = new SqlCommand(sql, conn))
{
// 添加参数并设置值
command.Parameters.AddWithValue("@Sid", "0001");
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine($"{reader["sid"]} {reader["sname"]} {reader["sex"]} {reader["age"]}");
}
}
}
}
Console.WriteLine("数据查询成功!");
}
catch (Exception ex)
{
Console.WriteLine("数据查询失败!"+ex.Message);
}
Console.ReadKey();
四、与其他技术集成
4.1、与XML集成
如何将DataSet转换为XML格式,以及如何从XML加载数据到DataSet中。
try
{
using (SqlConnection conn = new SqlConnection(str))
{
conn.Open();
string sql = "SELECT * FROM Student";
DataSet ds = new DataSet();
SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sql, conn);
sqlDataAdapter.Fill(ds);
//DataSet转化为xml
ds.WriteXml("output.xml");
Console.WriteLine("output.xml转化成功!");
//xml转化为DataSet
// 创建一个新的DataSet对象
DataSet dataSet = new DataSet();
// 从XML文件加载数据到DataSet中
dataSet.ReadXml("input.xml");
for (int i = 0; i<dataSet.Tables[0].Rows.Count; i++)
{
Console.WriteLine($"{dataSet.Tables[0].Rows[i][0]} {dataSet.Tables[0].Rows[i][1]} {dataSet.Tables[0].Rows[i][2]} {dataSet.Tables[0].Rows[i][3]}");
}
}
Console.WriteLine("转化成功!");
}
catch (Exception ex)
{
Console.WriteLine("转化失败!" + ex.Message);
}
Console.ReadKey();