SqlDataReader

C# ADO.NET 调用存储过程 和 SqlDataReader

调用SQL Server存储过程,使用SqlDataReader流式读取查询结果,核心要点:

  1. SqlCommand.CommandType = CommandType.StoredProcedure 标记执行存储过程
  2. 使用SqlParameter传递存储过程参数
  3. ExecuteReader(CommandBehavior.CloseConnection) 读取数据流
  4. SqlDataReader是向前只读、流式读取器,用完必须关闭

存储过程定义

读者需要到数据库中事先创建好存储过程,然后才可以调用。

create proc myProc
@id int
as
select * from [dbo].[Article] where id>@id
go

-- 调用测试
exec myProc @id=5Code language: JavaScript (javascript)

接收参数@id,查询Article表中id大于传入值的数据。

C#中调用存储过程

使用ExecuteReader返回SqlDataReader ,可以获取多条数据。

string connectionString = "Data Source=.;Initial Catalog=db;Integrated Security=SSPI;";
using (SqlConnection conn = new SqlConnection(connectionString))
{
    conn.Open();
    SqlCommand sqlCom = new SqlCommand();
    sqlCom.Connection = conn;
    sqlCom.CommandText = "myProc";
    sqlCom.CommandType = CommandType.StoredProcedure;

    SqlParameter param = new SqlParameter("@id", SqlDbType.Int, 8);
    param.Value = 4;
    param.Direction = ParameterDirection.Input;
    sqlCom.Parameters.Add(param);

    SqlDataReader reader = sqlCom.ExecuteReader(CommandBehavior.CloseConnection);
    StringBuilder sb = new StringBuilder();
    while (reader.Read())
    {
        sb.AppendLine(reader[0] + "-" + reader[1]);
    }
    reader.Close();
    MessageBox.Show(sb.ToString());
}Code language: C# (cs)
using释放Reader,避免资源泄漏
string connectionString = "Data Source=.;Initial Catalog=db;Integrated Security=SSPI;";
using (SqlConnection conn = new SqlConnection(connectionString))
{
    conn.Open();
    using (SqlCommand sqlCom = new SqlCommand("myProc", conn))
    {
        sqlCom.CommandType = CommandType.StoredProcedure;//表明命令是存储过程
        // 添加输入参数
        sqlCom.Parameters.Add("@id", SqlDbType.Int).Value = 4;

        // CommandBehavior.CloseConnection:reader关闭时自动关闭连接
        using (SqlDataReader reader = sqlCom.ExecuteReader(CommandBehavior.CloseConnection))
        {
            StringBuilder sb = new StringBuilder();
            while (reader.Read())
            {
                // reader[0]第1列,reader[1]第2列;也可以写reader["列名"]
                sb.AppendLine($"{reader[0]}-{reader[1]}");
            }
            MessageBox.Show(sb.ToString());
        }
        // 不需要手动reader.Close(),using会自动释放
    }
}Code language: C# (cs)

CommandType 三种枚举

  • CommandType.Text:执行普通SQL语句
  • CommandType.StoredProcedure执行存储过程
  • CommandType.TableDirect:直接读取数据表

不设置StoredProcedure,程序会把存储过程名当成普通SQL执行,直接报错!

SqlParameter 参数方向

  • ParameterDirection.Input:输入参数(传入值,最常用)
  • ParameterDirection.Output:输出参数
  • ParameterDirection.InputOutput:输入输出双向
  • ParameterDirection.ReturnValue:存储过程返回值

CommandBehavior.CloseConnection 作用

SqlDataReader调用Close()/释放时,自动关闭关联的SqlConnection
适合场景:方法返回Reader对象,外部读完数据后自动回收连接。

SqlDataReader 重要特性

  1. 只进只读:只能Read()向下遍历,不能回头、不能修改数据
  2. 连接占用:Reader打开期间,数据库连接不能执行其他操作
  3. 资源必须释放:要么手动reader.Close(),优先使用using自动释放
  4. 读取列两种方式:
    csharp reader[0]; // 通过索引读取 reader["Title"]; // 通过字段名读取(可读性更强)

注意

  1. 忘记设置 CommandType.StoredProcedure → 执行异常
  2. 参数名称大小写、拼写和存储过程不一致 → 参数不匹配
  3. Reader没有关闭 → 数据库连接持续占用,造成连接池耗尽
  4. while(reader.Read())内部执行新数据库查询:同一个连接不能同时多个Reader
  5. 存储过程参数缺失、参数类型不匹配 → 执行报错

对比

执行方式适用场景返回对象
ExecuteNonQuery增删改存储过程受影响行数 int
ExecuteScalar返回单行单列(聚合查询)object
ExecuteReader返回多行数据集SqlDataReader(流式读取)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注