【.NET全栈】ASP.NET开发Web应用——ADO.NET数据访问技术

文章目录

  • 前言
  • 一、ADO.NET基础
    • 1、ADO.NET架构
    • 2、ADO.NET数据提供者
  • 二、连接数据库
    • 1、SqlConnection数据库连接类
    • 2、使用SqlConnectionStringBuilder连接字符串
    • 3、关闭和释放连接
    • 4、在web.config配置文件中保存连接字符串
    • 5、连接池技术
  • 三、与数据库交互
    • 1、使用SqlCommand操作数据库
    • 2、为SqlCommand传递参数
    • 3、使用SqlCommand执行存储过程
    • 4、使用事务
    • 5、使用DataAdapter对象
  • 四、管理内存数据
    • 1、了解数据集
    • 2、使用DataTable实现内存表
    • 3、使用DataSet管理数据
    • 4、使用Reader获取只读数据
    • 5、比较DataSet和DataReader


前言

接下来介绍数据库驱动的ASP.NET应用程序。大多数Web应用程序都是基于数据库。比如电子商务平台,各大监控平台。

数据库具有强大、灵活的后端管理与存储数据的能力

ADO.NET则是应用程序和数据库之间的数据访问层,ASP.NET通过ADO.NET来操作数据库。ADO.NET本身也是基于多层架构设计,除了应用于普通的应用程序中,在分布式系统开发中,同样具有强大的功能。

本章内容有:

  • 认识ADO.NET数据访问技术
  • 连接数据库
  • 与数据库进行交互
  • 管理内存中的数据

一、ADO.NET基础

微软在.NET Framework中集成了最新的ADO.NET,已经是4.0版本。ADO.NET 4.0基本保持了和ADO.NET 2.0一致的特性,但是在4.0版本,微软集成了
语言集成查询(LINQ)的功能,这是一项重大的技术改进。后面会专门有一章介绍LINQ技术。

1、ADO.NET架构

ADO.NET类位于System.Data.dll中,并且与System.Xml.dll中的XML类紧密集成,ADO.NET中的类从总体上可以分为两大类:

  • 连接类型:提供连接到数据库,操作数据库数据的功能。
  • 断开类型:提供离线编辑与处理数据,在处理完成后交由连接类型进行数据的更新。

ADO.NET中的大多数类位于System.Data命名空间及其子命名空间中。System.Data命名空间包括ADO.NET提供的各种进行数据访问和处理的类。

特定的某类数据库的操作位于System.Data中不同的子类中,例如System.Data.SqlClient是关于SQL Server数据库的,System.Data.OleDB是关于Access数据库的,System.Data.MySql是关于MySQL数据库的。

【.NET全栈】ASP.NET开发Web应用——ADO.NET数据访问技术_第1张图片

2、ADO.NET数据提供者

数据提供者对象:

数据类 说明
Connection对象 数据连接对象,建立与物理数据库的连接
Transaction对象 数据库事务对象,与事务处理相关的类
DataAdapter对象 一个中间对象,一方面从数据库中获取数据并填充到DataSet对象中,另一方面用来将DataSet中更改的数据更细到数据库中,该对象介于连接对象与非连接对象之间,因此可看做一个适配器
Command对象 数据命令对象,ADO.NET中使用这个对象向数据库发送查询、更新、删除、修改操作的SQL语句
Parameter对象 参数对象,为Command对象中的SQL语句提供参数
DataReader 数据读取器对象,提供只读前项的游标,用于快速读取数据

数据库中数据提供者(没有提供统一的类,因此不同数据库采用不同操作对象):

数据提供者 说明
SQL Server提供者 为SQL Server提供优化访问的类
OLEDB提供者 提供对有OLEDB驱动程序的任何数据源的访问,如SQL Server或Oracle
Oracle提供者 为Oracle提供访问的类
ODBC提供者 对具有ODBC驱动的任何数据源的访问

二、连接数据库

1、SqlConnection数据库连接类

using System;  
using System.Data;  
using System.Data.SqlClient;  
  
class Program  
{  
    static void Main()  
    {  
        // 数据库连接字符串  
        string connectionString = "Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;";  
  
        // 使用SqlConnection连接数据库  
        using (SqlConnection connection = new SqlConnection(connectionString))  
        {  
            try  
            {  
                // 打开连接  
                connection.Open();  
  
                // 准备SQL查询  
                string sql = "SELECT TOP 10 * FROM MyTable";  
  
                // 创建SqlCommand  
                using (SqlCommand command = new SqlCommand(sql, connection))  
                {  
                    // 执行查询并获取结果  
                    using (SqlDataReader reader = command.ExecuteReader())  
                    {  
                        // 读取数据  
                        while (reader.Read())  
                        {  
                            Console.WriteLine(String.Format("{0}, {1}", reader[0], reader[1]));  
                        }  
                    }  
                }  
            }  
            catch (Exception ex)  
            {  
                // 异常处理  
                Console.WriteLine(ex.Message);  
            }  
        }  
    }  
}

这段代码首先创建了一个SqlConnection对象,并打开数据库连接。然后,它创建了一个SqlCommand对象来执行SQL查询,并使用SqlDataReader来读取查询结果。最后,它遍历结果集并打印出每一行的前两个字段。

请确保将connectionString变量中的myServerAddress、myDataBase、myUsername和myPassword替换为实际的数据库服务器地址、数据库名称、用户名和密码。

2、使用SqlConnectionStringBuilder连接字符串

using System;  
using System.Data.SqlClient;  
  
class Program  
{  
    static void Main()  
    {  
        // 创建SqlConnectionStringBuilder实例  
        SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();  
  
        // 设置服务器地址(数据源)  
        builder.DataSource = "myServerAddress";  
  
        // 设置初始数据库  
        builder.InitialCatalog = "myDataBase";  
  
        // 设置用户ID  
        builder.UserID = "myUsername";  
  
        // 设置密码  
        builder.Password = "myPassword";  
  
        // 如果需要,可以设置其他属性,比如连接超时时间  
        builder.ConnectTimeout = 30;  
  
        // 获取完整的连接字符串  
        string connectionString = builder.ToString();  
  
        // 使用连接字符串  
        using (SqlConnection connection = new SqlConnection(connectionString))  
        {  
            try  
            {  
                // 打开连接  
                connection.Open();  
  
                // 在这里执行数据库操作  
                Console.WriteLine("数据库连接成功!");  
            }  
            catch (Exception ex)  
            {  
                // 异常处理  
                Console.WriteLine("数据库连接失败:" + ex.Message);  
            }  
        }  
    }  
}

在这个示例中,我们首先创建了一个SqlConnectionStringBuilder的实例,并使用其属性来设置服务器地址、初始数据库、用户ID和密码。然后,我们使用ToString方法来获取完整的连接字符串,并使用它来创建一个SqlConnection对象。最后,我们尝试打开数据库连接,并在控制台中输出连接成功或失败的消息。

3、关闭和释放连接

using System;  
using System.Data.SqlClient;  
  
class Program  
{  
    static void Main()  
    {  
        // 数据库连接字符串  
        string connectionString = "Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;";  
  
        // 创建SqlConnection实例  
        using (SqlConnection connection = new SqlConnection(connectionString))  
        {  
            try  
            {  
                // 打开连接  
                connection.Open();  
  
                // 在这里执行数据库操作,例如查询、更新等  
  
                // ... 数据库操作代码 ...  
  
            }  
            catch (Exception ex)  
            {  
                // 异常处理  
                Console.WriteLine("数据库操作发生异常:" + ex.Message);  
            }  
            finally  
            {  
                // 关闭连接  
                if (connection.State == System.Data.ConnectionState.Open)  
                {  
                    connection.Close();  
                }  
  
                // 注意:由于使用了using语句,连接会在代码块结束时自动释放,  
                // 所以这里的Close调用其实是多余的,但它展示了如何显式关闭连接。  
            }  
  
            // 连接已经关闭并释放,using语句块结束时会自动调用connection的Dispose方法。  
        }  
  
        // 连接已经完全关闭并释放,可以在这里进行后续操作或退出程序。  
        Console.WriteLine("数据库连接已关闭并释放。");  
    }  
}

在这个例子中,SqlConnection对象是在using语句块中创建的。using语句确保了在代码块执行完毕后,SqlConnection对象的Dispose方法会被自动调用,从而释放连接所占用的资源。即使发生异常,using语句也会保证Dispose方法被调用。

由于using语句已经提供了自动的资源管理,所以在finally块中显式调用connection.Close()其实是多余的。然而,这个调用展示了如何在不使用using语句的情况下显式关闭数据库连接。在实际应用中,推荐使用using语句来管理数据库连接和其他需要释放资源的对象。

4、在web.config配置文件中保存连接字符串

步骤 1: 编辑web.config文件
打开你的ASP.NET项目中的web.config文件,找到或添加标签下的标签。在这个标签中,你可以定义一个或多个连接字符串。

<configuration>
  ...
  <connectionStrings>
    <add name="MyConnectionString"
         connectionString="Data Source=myServerAddress;Initial Catalog=myDataBase;User Id=myUsername;Password=myPassword;"
         providerName="System.Data.SqlClient" />
  </connectionStrings>
  ...
</configuration>

在这个示例中,name属性是用于在代码中引用连接字符串的名称。connectionString属性包含了实际的数据库连接信息,包括服务器地址、数据库名称、用户名和密码等。providerName属性指定了数据提供程序的名称,这里使用的是System.Data.SqlClient,适用于SQL Server。

步骤 2: 在代码中使用连接字符串
在你的ASP.NET应用代码中,你可以通过ConfigurationManager.ConnectionStrings属性来访问在web.config中定义的连接字符串。以下是一个使用C#的示例:

using System.Configuration;

string connectionString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;

using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    // 在这里执行你的数据库操作
}

在这个例子中,MyConnectionString是我们在web.config中定义的连接字符串的名称,通过ConfigurationManager.ConnectionStrings获取到连接字符串,然后使用它来创建SqlConnection对象。

通过这种方式,你可以确保连接字符串的安全性和可维护性,同时避免硬编码敏感信息到代码中。

5、连接池技术

连接池技术是一种用于管理数据库连接的优化策略,它允许应用程序重复使用现有的数据库连接,而不是为每个数据库操作创建新的连接。这样可以显著减少建立和关闭连接所需的时间,提高应用程序的性能和可扩展性。在ASP.NET中,连接池是由.NET Framework的数据提供程序自动管理的,特别是System.Data.SqlClient提供程序。

连接池的工作原理是,当第一个连接请求到达时,连接池会被创建(如果还不存在),并且该连接会被添加到池中。随后的连接请求会检查连接池,以查看是否有可用的连接可以重用。如果找到合适的连接,它会被取出供应用程序使用;如果没有可用连接,将创建一个新连接并添加到池中。连接池中的连接在一段时间不活跃后可能会被清除,以释放资源。

连接池的配置和使用
在ASP.NET应用程序中,连接池的配置通常在web.config文件的节中进行。可以通过设置连接字符串属性来控制连接池的行为,例如Max Pool Size(最大池大小)和Min Pool Size(最小池大小)。默认情况下,连接池是启用的,但可以通过在连接字符串中设置Pooling=false来禁用它。

代码示例
以下是一个使用System.Data.SqlClient连接字符串的示例,展示了如何在web.config文件中配置连接池:

<configuration>
 <connectionStrings>
    <add name="MyConnectionString"
         connectionString="Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;Integrated Security=SSPI;Max Pool Size=100;Min Pool Size=0;Pooling=true;"
         providerName="System.Data.SqlClient" />
 </connectionStrings>
</configuration>

在C#代码中,可以通过SqlConnection类的ConnectionString属性来访问配置的连接字符串,并打开连接。连接在使用完毕后应该被关闭,以便它可以返回到连接池中供后续使用:

using System.Data.SqlClient;

string connectionString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    // 执行数据库操作
} // 连接在using语句块结束时自动关闭,返回连接池

注意事项

  • 确保所有数据库连接在使用完毕后都被关闭,以便它们可以被重新利用。
  • 避免在类的终结器中关闭数据库连接,因为这可能会阻止连接返回到池中。
  • 监控连接池的性能,确保连接池的大小适合应用程序的需求,以避免资源耗尽或不必要的等待。

三、与数据库交互

在建立与数据源的连接后,通常是执行从数据库中获取数据,添加、删除、更改、查询数据库中的数据操作。ADO.NET提供了Command对象用于向数据库下达SQL指令,以及从数据库获取查询结果等功能。

1、使用SqlCommand操作数据库

在ASP.NET应用程序中,SqlCommand类是用来执行SQL命令的关键类,它属于System.Data.SqlClient命名空间。通过SqlCommand对象,您可以执行各种数据库操作,包括但不限于执行SQL语句、存储过程、查询、插入、更新和删除数据。SqlCommand对象提供了多种属性和方法,允许您配置和执行数据库命令,并处理命令执行的结果。

SqlCommand的基本使用方法:

创建SqlCommand对象
可以通过传递SQL命令文本和SqlConnection对象到SqlCommand的构造函数来创建一个SqlCommand对象。例如:

string connectionString = "YourConnectionStringHere";
using (SqlConnection connection = new SqlConnection(connectionString))
{
    string queryString = "SELECT * FROM YourTableName";
    SqlCommand command = new SqlCommand(queryString, connection);
    // 其他命令配置和执行代码...
}

执行SqlCommand对象

SqlCommand对象提供了多种方法来执行SQL命令,包括ExecuteReader、ExecuteNonQuery和ExecuteScalar。ExecuteReader用于执行查询并返回SqlDataReader对象,ExecuteNonQuery用于执行不会返回数据集的命令(如INSERT、UPDATE、DELETE),而ExecuteScalar用于执行返回单个值的查询。

// 使用ExecuteReader执行查询
using (SqlConnection connection = new SqlConnection(connectionString))
{
    string queryString = "SELECT * FROM YourTableName";
    SqlCommand command = new SqlCommand(queryString, connection);
    connection.Open();
    SqlDataReader reader = command.ExecuteReader();
    // 处理查询结果...
}

// 使用ExecuteNonQuery执行非查询命令
using (SqlConnection connection = new SqlConnection(connectionString))
{
    string insertString = "INSERT INTO YourTableName (Column1, Column2) VALUES (@value1, @value2)";
    SqlCommand command = new SqlCommand(insertString, connection);
    command.Parameters.AddWithValue("@value1", yourValue1);
    command.Parameters.AddWithValue("@value2", yourValue2);
    connection.Open();
    command.ExecuteNonQuery();
}

// 使用ExecuteScalar执行返回单个值的查询
using (SqlConnection connection = new SqlConnection(connectionString))
{
    string countString = "SELECT COUNT(*) FROM YourTableName";
    SqlCommand command = new SqlCommand(countString, connection);
    connection.Open();
    int count = (int)command.ExecuteScalar();
}

配置SqlCommand对象

SqlCommand对象提供了多种属性来配置命令,包括CommandText、CommandType、Connection、CommandTimeout和Parameters。CommandType属性用于指定命令文本是SQL语句还是存储过程的名称。Parameters集合用于添加命令参数,这有助于防止SQL注入攻击并确保数据的正确传递。

// 配置命令参数
using (SqlConnection connection = new SqlConnection(connectionString))
{
    string queryString = "SELECT * FROM YourTableName WHERE Column1 = @value1 AND Column2 = @value2";
    SqlCommand command = new SqlCommand(queryString, connection);
    command.Parameters.AddWithValue("@value1", yourValue1);
    command.Parameters.AddWithValue("@value2", yourValue2);
    // 其他命令配置和执行代码...
}

最佳实践和安全措施

  • 始终使用参数化查询来预防SQL注入攻击。
  • 使用using语句来确保即使发生异常也能正确关闭数据库连接。
  • 根据需要调整CommandTimeout属性,以防止长时间运行的命令导致连接超时。

2、为SqlCommand传递参数

在ASP.NET中,使用SqlCommand对象执行数据库命令时,传递参数是非常重要的做法,它不仅可以提高代码的安全性,防止SQL注入攻击,还可以提高代码的可读性和可维护性。以下是为SqlCommand传递参数的步骤和代码示例。

步骤:

  • 创建SqlCommand对象:使用SQL命令文本和SqlConnection对象初始化SqlCommand对象。

  • 配置参数:使用SqlCommand对象的Parameters集合添加参数。每个参数都应该有一个唯一的名称,并且可以指定其数据类型、方向(输入、输出或两者兼有)以及值。

  • 执行命令:使用ExecuteReader、ExecuteNonQuery或ExecuteScalar等方法根据需要执行命令。

代码示例

using System.Data.SqlClient;

string connectionString = "YourConnectionStringHere";
using (SqlConnection connection = new SqlConnection(connectionString))
{
    string queryString = "INSERT INTO YourTableName (Column1, Column2) VALUES (@value1, @value2)";
    SqlCommand command = new SqlCommand(queryString, connection);

    // 添加参数并设置值
    command.Parameters.AddWithValue("@value1", yourValue1);
    command.Parameters.AddWithValue("@value2", yourValue2);

    // 打开连接并执行命令
    connection.Open();
    command.ExecuteNonQuery();
}

在上述代码中,AddWithValue方法用于快速添加参数,它会根据传递的值推断参数的数据类型。此外,还可以使用SqlParameter类显式创建参数,并设置其详细信息,如下所示:

using System.Data.SqlClient;

string connectionString = "YourConnectionStringHere";
using (SqlConnection connection = new SqlConnection(connectionString))
{
    string queryString = "INSERT INTO YourTableName (Column1, Column2) VALUES (@value1, @value2)";
    SqlCommand command = new SqlCommand(queryString, connection);

    // 使用SqlParameter显式创建参数
    SqlParameter param1 = new SqlParameter("@value1", SqlDbType.VarChar);
    param1.Value = yourValue1;
    SqlParameter param2 = new SqlParameter("@value2", SqlDbType.Int);
    param2.Value = yourValue2;

    // 将参数添加到命令中
    command.Parameters.Add(param1);
    command.Parameters.Add(param2);

    // 打开连接并执行命令
    connection.Open();
    command.ExecuteNonQuery();
}

在实际应用中,应根据具体情况选择使用AddWithValue方法或SqlParameter类来添加参数。如果需要更精细的控制参数的数据类型或其他属性,建议使用SqlParameter类。同时,确保传递的参数值已经过适当的验证和清理,以避免安全风险。

3、使用SqlCommand执行存储过程

在ASP.NET中,使用SqlCommand对象执行存储过程是一种常见的数据库操作方式,它允许您利用存储过程的优势,如提高性能、重用代码和增强安全性。以下是执行存储过程的步骤和代码示例。

步骤

  • 创建SqlCommand对象:设置SqlCommand对象的CommandType属性为CommandType.StoredProcedure,并指定存储过程的名称。

  • 配置参数:如果存储过程需要输入或输出参数,使用SqlCommand对象的Parameters集合来添加这些参数。

  • 执行存储过程:使用ExecuteNonQuery方法执行不会返回数据集的存储过程(如INSERT、UPDATE、DELETE),或者使用ExecuteReader方法执行返回数据集的存储过程(如SELECT)。

using System.Data.SqlClient;

string connectionString = "YourConnectionStringHere";
using (SqlConnection connection = new SqlConnection(connectionString))
{
    // 创建SqlCommand对象,设置为执行存储过程
    SqlCommand command = new SqlCommand("YourStoredProcedureName", connection);
    command.CommandType = CommandType.StoredProcedure;

    // 添加存储过程参数(如果有)
    command.Parameters.AddWithValue("@ParameterName", value);

    // 打开连接并执行存储过程
    connection.Open();
    command.ExecuteNonQuery(); // 或者使用 command.ExecuteReader() 来执行返回数据集的存储过程
}

在上述代码中,YourStoredProcedureName是存储过程的名称,@ParameterName是存储过程中定义的参数名称,value是传递给参数的值。如果存储过程返回结果集,可以使用ExecuteReader方法代替ExecuteNonQuery方法来获取数据。

注意事项

  • 确保存储过程的名称和参数与数据库中定义的一致。
  • 使用参数化查询来防止SQL注入攻击。
  • 处理可能抛出的异常,确保应用程序的健壮性。
  • 在执行完数据库操作后,使用connection.Close()或using语句确保数据库连接被正确关闭。

4、使用事务

在ASP.NET中,使用SqlCommand对象管理事务可以确保一系列数据库操作要么全部成功,要么在遇到错误时全部回滚,从而保持数据库的完整性。以下是使用SqlCommand执行事务的步骤和代码示例。

步骤

  • 创建SqlConnection对象并打开连接。

  • 创建SqlCommand对象并将其Connection属性设置为步骤1中创建的SqlConnection对象。

  • 创建SqlTransaction对象并使用SqlConnection对象的BeginTransaction方法开始一个新的事务。

  • 将SqlCommand对象的Transaction属性设置为步骤3中创建的SqlTransaction对象。

  • 执行数据库操作,如使用ExecuteNonQuery、ExecuteReader或ExecuteScalar方法。

  • 在所有操作完成后,根据操作的成功与否决定提交或回滚事务。使用Transaction.Commit方法提交事务,使用Transaction.Rollback方法回滚事务。

  • 确保在操作完成后关闭数据库连接。

using System.Data.SqlClient;

string connectionString = "YourConnectionStringHere";
using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    
    SqlCommand command = connection.CreateCommand();
    SqlTransaction transaction = connection.BeginTransaction();
    
    command.Connection = connection;
    command.Transaction = transaction;
    
    try
    {
        command.CommandText = "INSERT INTO YourTableName (Column1, Column2) VALUES (@value1, @value2)";
        command.Parameters.AddWithValue("@value1", yourValue1);
        command.Parameters.AddWithValue("@value2", yourValue2);
        
        command.ExecuteNonQuery();
        
        // 可以继续添加更多的数据库操作命令
        
        // 提交事务
        transaction.Commit();
    }
    catch (Exception ex)
    {
        // 回滚事务
        transaction.Rollback();
        // 处理异常
    }
}

在上述代码中,yourValue1和yourValue2是传递给存储过程的参数值。AddWithValue方法用于添加参数,它会根据传递的值推断参数的数据类型。如果需要更精细的控制,可以使用SqlParameter类显式创建参数。

注意事项

  • 确保在执行数据库操作前后正确处理事务,以防止部分完成的操作导致数据不一致。
  • 使用try…catch块来捕获可能发生的异常,并据此决定回滚或提交事务。
  • 在事务完成后,使用connection.Close()或using语句确保数据库连接被正确关闭。

5、使用DataAdapter对象

DataAdapter对象在.NET中是一个重要的数据访问类,它提供了一种简便的方式来同步数据表与数据库之间的数据。DataAdapter可以执行填充(Fill)、更新(Update)、删除(Delete)和插入(Insert)操作。以下是使用DataAdapter对象的基本步骤和代码示例。

使用DataAdapter对象的步骤

  • 创建DataAdapter实例:可以通过传递SQL查询字符串和SqlConnection对象到DataAdapter的构造函数来创建实例。

  • 设置命令属性:DataAdapter有四个命令属性(SelectCommand, InsertCommand, UpdateCommand, DeleteCommand),分别对应不同的数据库操作。

  • 填充DataSet或DataTable:使用DataAdapter的Fill方法将数据从数据库填充到DataSet或指定的DataTable中。

  • 更新数据库:对DataSet或DataTable中的数据进行修改后,可以使用DataAdapter的Update方法将这些更改应用回数据库。

  • 处理异常和事务:在执行数据操作时,应当妥善处理可能出现的异常,并考虑使用事务来确保数据的一致性。

using System.Data;
using System.Data.SqlClient;

// 创建连接字符串
string connectionString = "YourConnectionStringHere";

// 创建SqlConnection实例
using (SqlConnection connection = new SqlConnection(connectionString))
{
    // 打开连接
    connection.Open();

    // 创建SqlDataAdapter实例
    string query = "SELECT * FROM YourTableName";
    SqlDataAdapter adapter = new SqlDataAdapter(query, connection);

    // 创建DataSet实例
    DataSet dataSet = new DataSet();

    // 填充DataSet
    adapter.Fill(dataSet, "YourTableName");

    // 更新数据集后应用更改回数据库
    // adapter.Update(dataSet, "YourTableName");

    // 关闭连接
    connection.Close();
}

在上述代码中,首先创建了一个SqlConnection实例和一个SqlDataAdapter实例,并通过SQL查询填充了DataSet。如果需要更新数据库,可以取消注释adapter.Update方法调用,并传入相应的DataSet和表名。

注意事项

  • 确保在使用DataAdapter之前,数据库连接已经打开。
  • 使用SqlCommandBuilder可以自动生成InsertCommand, UpdateCommand, 和 DeleteCommand,这在处理简单的CRUD操作时非常有用。
  • 在更新数据库之前,检查DataSet中的数据是否符合预期,以避免不必要的数据损坏。
  • 处理完毕后,确保关闭数据库连接,释放资源。

四、管理内存数据

DataSet类是ADO.NET中非连接类型最主要的类。该类就像一个小型的内存数据库系统。在该类中具有数据表、数据列、数据行、约束、表间关系等特性,DataSet为异构的数据源之间提供了一致的编程模型。

1、了解数据集

  1. 数据集(DataSet)的概念
    数据集(DataSet)是.NET框架中的一个强大的数据管理类,它允许您在应用程序中缓存数据,并提供了一系列用于操作这些数据的方法。数据集可以包含多个数据表,这些数据表可以是从数据库检索的,也可以是在应用程序中动态创建的。数据集提供了对数据进行浏览、编辑、排序、过滤和建立视图的能力,并且可以在不与数据库保持持续连接的情况下工作。

  2. 数据集的特点

  • 非连接性:数据集在读取数据后与数据库断开连接,允许其他用户继续使用数据源。
  • 数据缓存:数据集在内存中存储数据,提高了数据操作的效率。
  • 结构化数据:数据集可以表示复杂的数据结构,包括表格、关系和约束。
  • 数据转换:数据集可以轻松地转换为XML格式,便于数据的交换和持久化。
  1. 数据集的使用场景
  • 在客户端应用程序中缓存数据,减少对数据库的直接访问次数。
  • 在多层应用程序中作为业务逻辑层和表示层之间的数据传递机制。
  • 在离线应用程序中存储和管理数据。
    【.NET全栈】ASP.NET开发Web应用——ADO.NET数据访问技术_第2张图片
using System.Data;
using System.Data.SqlClient;

// 创建连接字符串
string connectionString = "YourConnectionStringHere";

// 创建SqlConnection实例
using (SqlConnection connection = new SqlConnection(connectionString))
{
    // 打开连接
    connection.Open();

    // 创建SqlDataAdapter实例
    string query = "SELECT * FROM YourTableName";
    SqlDataAdapter adapter = new SqlDataAdapter(query, connection);

    // 创建DataSet实例
    DataSet dataSet = new DataSet();

    // 填充DataSet
    adapter.Fill(dataSet, "YourTableName");

    // 使用dataSet进行后续操作,例如绑定到控件等
}

在这个示例中,首先创建了一个SqlConnection和SqlDataAdapter实例,然后通过执行SQL查询填充了DataSet。DataSet可以用来绑定到ASP.NET页面上的控件,如GridView,以便在前端显示数据。

注意事项

  • 确保在使用数据集之前,数据库连接已经打开。
  • 数据集在使用完毕后应该被适当清理,以释放资源。
  • 在处理数据集时,应注意异常管理和事务控制,以保证数据的一致性和完整性。

2、使用DataTable实现内存表

在.NET中,DataTable是DataSet的一个组成部分,但它同样可以独立使用来创建内存中的数据表。DataTable对象提供了一种在应用程序内存中创建和操作结构化数据的方法,类似于数据库中的表格。以下是如何使用DataTable创建和操作内存表的步骤和代码示例。

创建DataTable对象

首先,需要创建一个DataTable对象,并定义其列和数据类型。可以使用Columns.Add方法来添加新列,并指定列的数据类型。

DataTable table = new DataTable("MyTable");
table.Columns.Add("ID", typeof(int));
table.Columns.Add("Name", typeof(string));
table.Columns.Add("Age", typeof(int));

添加数据行
使用NewRow方法创建新的数据行,然后使用Add方法将行添加到DataTable中。

DataRow row = table.NewRow();
row["ID"] = 1;
row["Name"] = "John Doe";
row["Age"] = 25;
table.Rows.Add(row);

数据操作
DataTable提供了许多方法来操作数据,包括查找、排序、过滤等。例如,可以使用DefaultView来对数据进行排序或过滤。

// 对表进行排序
table.DefaultView.Sort = "Age DESC";
var sortedTable = table.DefaultView.ToTable();

// 过滤数据
var filteredView = table.DefaultView.RowFilter = "Age > 20";
var filteredTable = filteredView.ToTable();

代码示例:创建和填充DataTable
下面是一个完整的示例,展示了如何创建和填充DataTable,并进行基本的数据操作。

using System;
using System.Data;

class Program
{
    static void Main()
    {
        // 创建DataTable
        DataTable table = new DataTable("Employees");
        table.Columns.Add("ID", typeof(int));
        table.Columns.Add("Name", typeof(string));
        table.Columns.Add("Department", typeof(string));

        // 添加数据
        table.Rows.Add(1, "John Doe", "IT");
        table.Rows.Add(2, "Jane Doe", "HR");
        table.Rows.Add(3, "Michael Smith", "IT");

        // 打印原始数据
        Console.WriteLine("Original Data:");
        foreach (DataRow row in table.Rows)
        {
            Console.WriteLine($"{row["ID"]} - {row["Name"]} - {row["Department"]}");
        }

        // 过滤数据
        DataView view = new DataView(table);
        view.RowFilter = "Department = 'IT'";
        DataTable filteredTable = view.ToTable();
        
        // 打印过滤后的数据
        Console.WriteLine("\nFiltered Data:");
        foreach (DataRow row in filteredTable.Rows)
        {
            Console.WriteLine($"{row["ID"]} - {row["Name"]} - {row["Department"]}");
        }
    }
}

在上面的示例中,首先创建了一个DataTable对象,并添加了三列。然后添加了几行数据。最后,创建了一个DataView对象,并使用RowFilter属性来过滤数据,只显示部门为“IT”的员工。

3、使用DataSet管理数据

在.NET Framework中,DataSet是一个内存中的数据表示,它可以包含来自数据库的数据或在应用程序中创建的数据。DataSet提供了一个结构化的环境,用于处理数据表、关系、约束等,并且可以在不与数据库直接通信的情况下进行本地数据操作。

创建DataSet
创建DataSet的基本步骤包括初始化DataSet对象,并根据需要添加DataTable对象。DataSet可以通过new DataSet()构造函数创建。

DataSet dataSet = new DataSet();

添加DataTable
DataSet可以包含一个或多个DataTable对象,这些对象代表数据表。可以通过Tables.Add方法向DataSet添加DataTable。

DataTable table = new DataTable();
dataSet.Tables.Add(table);

定义DataTable结构
在DataTable中定义列和数据类型是通过Columns集合完成的。可以使用Columns.Add方法来添加新列,并指定列的数据类型。

table.Columns.Add("ColumnName", System.Data.DataType.Int32);

填充DataTable
DataSet可以通过多种方式填充数据,包括手动添加行、使用DataAdapter从数据库填充,或者通过序列化和反序列化操作。

// 手动添加行
DataRow row = table.NewRow();
row["ColumnName"] = 123;
table.Rows.Add(row);

// 使用DataAdapter填充
using (SqlConnection connection = new SqlConnection(connectionString))
{
    using (SqlDataAdapter adapter = new SqlDataAdapter(selectQuery, connection))
    {
        adapter.Fill(dataSet, "TableName");
    }
}

操作DataSet
DataSet提供了一系列方法来操作数据,包括添加、删除、修改行,以及遍历数据集。

// 遍历DataSet
foreach (DataTable table in dataSet.Tables)
{
    foreach (DataRow row in table.Rows)
    {
        // 处理每一行数据
    }
}

保存和加载DataSet
DataSet可以保存到磁盘上,也可以从磁盘加载。保存通常通过WriteXml方法完成,加载则通过ReadXml方法。

// 保存DataSet到XML文件
dataSet.WriteXml("path_to_file.xml");

// 从XML文件加载DataSet
dataSet.ReadXml("path_to_file.xml");

注意事项

  • 在操作DataSet时,应当注意异常管理,确保数据的一致性和完整性。
  • 在处理大型数据集时,应考虑性能优化,如使用批处理操作和适当的数据结构。

4、使用Reader获取只读数据

在.NET框架中,DataReader是一个高性能的数据读取器,它提供了一个只读、只前进的数据访问接口。DataReader允许您从数据库或其他数据源中检索数据,而无需将数据缓存到内存中的数据集中。这使得DataReader非常适合处理大量数据,因为它减少了内存占用并提高了读取速度。

使用SqlCommand和SqlConnection创建DataReader
要使用DataReader获取数据,您需要先创建一个SqlConnection对象来建立与数据库的连接,然后创建一个SqlCommand对象来定义要执行的SQL命令。最后,通过执行SqlCommand对象的ExecuteReader方法来获取DataReader实例。

using System;
using System.Data;
using System.Data.SqlClient;

class Program
{
    static void Main()
    {
        string connectionString = "YourConnectionStringHere";
        string query = "SELECT ID, Name, Age FROM Employees";

        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            SqlCommand command = new SqlCommand(query, connection);
            connection.Open();

            using (SqlDataReader reader = command.ExecuteReader())
            {
               while (reader.Read())
               {
                    int employeeId = reader.GetInt32(0);
                    string employeeName = reader.GetString(1);
                    int employeeAge = reader.GetInt32(2);

                    // Process the data here
               }
            }
        }
    }
}

在上述代码中,connectionString是您的数据库连接字符串,query是您想要执行的SQL SELECT语句。通过using语句块确保SqlConnection和SqlDataReader在使用完毕后正确关闭和释放资源。

DataReader的特点

  • 只读:一旦数据被DataReader读取,它就不能被修改。
  • 只前进:DataReader只能向前移动,不能后退或跳转到其他记录。
  • 高性能:由于数据是直接从数据源流向应用程序的,不经过中间缓存,因此DataReader在处理大数据集时表现出色。
  • 资源管理:DataReader实现了IDisposable接口,确保在使用完毕后释放相关资源。

注意事项

  • 在使用DataReader时,应该注意异常处理,尤其是在打开和关闭数据库连接时。
  • 确保数据库连接字符串安全,避免硬编码敏感信息。
  • 在处理DataReader时,应该注意数据类型的正确匹配,使用GetXXX方法来获取相应的数据字段。

5、比较DataSet和DataReader

DataSet和DataReader是.NET框架中用于处理数据的两种不同的类。DataSet是一个内存中的数据表示,可以包含来自数据库的数据表、关系、约束等,支持离线操作,可以在不连接数据库的情况下对数据进行修改和管理。DataReader则是一个只读、前向的数据流,用于高效地从数据库中逐行读取数据,它在读取数据时保持数据库连接开放,直到读取操作完成。

【.NET全栈】ASP.NET开发Web应用——ADO.NET数据访问技术_第3张图片

你可能感兴趣的:(#,.NET全栈,.net,asp.net,前端)