【问题标题】:SQL DataReader missing a row in loopSQL DataReader 在循环中缺少一行
【发布时间】:2008-11-20 05:38:18
【问题描述】:

运行以下代码时,它会遗漏一行。当我执行 files.Count 时,它说有 4 行,但没有为第 4 行存储数据。当我从 SQL 管理器中运行存储过程时,它会返回所有 4 行和所有数据。有什么帮助吗?

            List<File> files = new List<File>();
            SqlConnection active_connection = new SqlConnection(m_connection_string);
            SqlCommand cmd = new SqlCommand();
            SqlDataReader dr = null;

            try
            {
                active_connection.Open();
                cmd.Connection = active_connection;
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.CommandText = "dalsp_Select_Organization_Files";

                SqlParameter param;

                param = cmd.Parameters.Add("@p_organization_guid", SqlDbType.UniqueIdentifier);
                param.Value = new Guid(organization_guid);

                param = cmd.Parameters.Add("@p_file_type", SqlDbType.NVarChar, 50);
                param.Value = file_type;

                dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);

                if (dr.HasRows)                    
                {                    
                    while (dr.Read())
                    {
                        File file = new File();
                        file.OrganizationGuid = dr["OrganizationGuid"].ToString();
                        file.FileGuid = dr["FileGuid"].ToString();
                        file.FileLocation = dr["FileLocation"].ToString();
                        file.FileName = dr["FileName"].ToString();
                        file.FileType = (FileTypeEnum)Enum.Parse(typeof(FileTypeEnum), dr["FileType"].ToString());
                        file.FileExtension = dr["FileExtension"].ToString();
                        file.FileDescription = dr["FileDescription"].ToString();
                        file.ThumbnailPath = dr["ThumbnailPath"].ToString();
                        files.Add(file);
                    }       
                }
                dr.Close();
                dr = null;

                active_connection.Close();
                cmd = null;

            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                if (active_connection.State != ConnectionState.Closed)
                {
                    active_connection.Close();
                    active_connection.Dispose();
                }
            }

            return files;

【问题讨论】:

    标签: c# sql datareader


    【解决方案1】:

    如果您说您的文件集合有 4 个项目,但 4 个项目不包含任何值,您的意思是什么?是null,对象没有数据,还是抛出索引超出范围异常?

    您是在做文件[4] 还是类似以下的事情?

    for(int x = 1; x < files.length; x++)
    {
         files[x]
    }
    

    那是行不通的。记住 C# 中基于 0 的索引。

    作为旁注,您可以通过执行以下操作来取消您的 try catch 语句:

    using (SqlConnection connection = new SqlConnection(conn_string))
    {
        connection.Open();
        using (SqlCommand cmd = new SqlCommand("SELECT * FROM MyTable", connection))
        {
             using (SqlDataReader dr = cmd.ExecuteReader())
             {
                 return result;
             }
        }
    }
    

    using 语句将保证读取器和连接的处置(并因此关闭)。

    【讨论】:

    • 感谢 Marc,因为我不再手动编写代码生成器了。
    • 哦,伙计.. 我想我盯着代码看太晚了。这就是问题所在 - 我正在尝试获取当然不存在的文件[4]。多么愚蠢的错误。谢谢您的帮助。我已经更改了代码,现在可以完美运行了。
    • 缺失:cmd.Connection = 连接;
    【解决方案2】:

    你应该放弃“if (dr.HasRows)”,它所做的只是在 while 循环中重复检查。

    您不应该在连接上调用 Close,也不应该将其设置为 null。相反,您应该将连接包装在“使用”块中,如下所示:

    using (SqlCommand cmd = new SqlCommand()) {
       //use the connection
    }
    

    数据阅读器和 SQL 命令也是如此。

    下一点什么都不做,删除它。

      catch (Exception) { throw; }            
    

    【讨论】:

    • catch (异常) { throw;如果您想在异常上设置断点,这很有用。它不应该受到伤害,我认为编译器会在发布版本中删除它
    【解决方案3】:

    您是否尝试过在调试器中单步执行此操作,并在执行阅读器之前检查您的命令参数?您在结果集中得到的值是否与直接在 sql 上运行 sproc 时相同?

    我可能是错的,因为有几种方法可以做到这一点,但是在您将参数添加到命令的方式中看起来有些奇怪。

    我通常使用的模式更像:

    SqlParameter param = new SqlParameter();  
    // set param stuff - here or in ctor   
    cmd.Parameters.Add(param);  
    

    主要是关于什么对你有用....

    我遇到存储过程问题的大部分时间是在我对参数进行处理时。

    【讨论】:

      【解决方案4】:

      代码在我看来是正确的。我认为您肯定希望通过调试器来查看从 ExecuteReader 返回了多少行。我的一条评论是“if (dr.HasRows)”有点多余,因为“while (dr.Read())”会给你同样的效果。

      我想问的另一个问题是,你知道你是错过了第一条记录还是最后一条记录吗?

      布赖恩

      【讨论】:

        猜你喜欢
        • 2019-10-13
        • 2019-05-30
        • 1970-01-01
        • 2012-11-02
        • 1970-01-01
        • 2020-02-22
        • 2014-05-03
        • 1970-01-01
        • 2012-08-11
        相关资源
        最近更新 更多