You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中使用IDataReader时遭遇IndexOutOfRangeException问题求助

问题:IDataReader调用GetDataValue时触发IndexOutOfRangeException异常

我在C#中使用IDataReader时遇到了IndexOutOfRangeException异常,该异常在执行GetDataValue方法时触发。

示例代码

业务查询方法

public List<Users> SelectUsersbyUsernamePassword(string username, string password)
{
    const string SQL_STATEMENT =
        "SELECT U.Username, U.Password, U.Role " +
        "FROM Users U ";

    List<Users> listusers = new List<Users>();
    Database db = new Microsoft.Practices.EnterpriseLibrary.Data.Sql.SqlDatabase(CONNECTION_NAME);

    using (DbCommand cmd = db.GetSqlStringCommand(SQL_STATEMENT))
    {
        db.AddInParameter(cmd, "@username", DbType.String, username);
        db.AddInParameter(cmd, "@password", DbType.String, password);
        try
        {
            using (IDataReader dr = db.ExecuteReader(cmd))
            {
                while (dr.Read())
                {
                    Users users = new Users();
                    users.UserID = base.GetDataValue<int>(dr, "UserID");
                    users.Username = base.GetDataValue<string>(dr, "Username");
                    users.Password = base.GetDataValue<string>(dr, "Password");
                    users.Role = base.GetDataValue<string>(dr, "Role");

                    listusers.Add(users);
                }
            }
        }
        catch (Exception ex)
        {
            throw ex;
            //throw new DbException(ex.Message, SQL_STATEMENT, "username = " + username, ex.InnerException);
        }
    }
    return listusers;
}

数据访问基础方法

protected T GetDataValue<T>(IDataReader dr, string columnName)
{
    int i = dr.GetOrdinal(columnName);

    if (!dr.IsDBNull(i))
        return (T)dr.GetValue(i);
    else
        return default(T);
}

问题原因分析

  • 直接触发异常的原因:SQL查询语句中只选择了Username、Password、Role三列,但代码中尝试读取UserID字段,GetOrdinal方法在找不到对应列名时会抛出IndexOutOfRangeException。
  • 附加逻辑问题:SQL语句未添加WHERE条件,当前会返回所有用户数据,完全没有利用传入的username和password参数做过滤,业务逻辑不符合预期。

修复方案

1. 修正SQL查询语句

补充UserID列的选择,并添加WHERE条件过滤用户:

const string SQL_STATEMENT =
    "SELECT U.UserID, U.Username, U.Password, U.Role " +
    "FROM Users U " +
    "WHERE U.Username = @username AND U.Password = @password";

2. (可选)增强GetDataValue的容错性

如果希望方法在列不存在时不抛出异常,可以增加列名存在性检查:

protected T GetDataValue<T>(IDataReader dr, string columnName)
{
    // 检查列是否存在于结果集中
    if (!dr.GetSchemaTable().AsEnumerable().Any(row => row["ColumnName"].ToString() == columnName))
        return default(T);
    
    int i = dr.GetOrdinal(columnName);
    if (!dr.IsDBNull(i))
        return (T)dr.GetValue(i);
    else
        return default(T);
}

内容的提问来源于stack exchange,提问作者RogerSK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 19:55:19