从 SqlDataReader 读取数据

Posted

技术标签:

【中文标题】从 SqlDataReader 读取数据【英文标题】:Read data from SqlDataReader 【发布时间】:2011-04-30 09:46:29 【问题描述】:

我有一个 SQL Server 2008 数据库,我正在后端处理它。我正在研究 asp.net/C#

SqlDataReader rdr = cmd.ExecuteReader();  
while (rdr.Read())  
              
   //how do I read strings here????  
  

我知道读者有价值观。我的 SQL 命令是从表中只选择 1 列。该列仅包含字符串。我想一一阅读阅读器中的字符串(行)。我该怎么做?

【问题讨论】:

【参考方案1】:
using(SqlDataReader rdr = cmd.ExecuteReader())

    while (rdr.Read())
    
        var myString = rdr.GetString(0); //The 0 stands for "the 0'th column", so the first column of the result.
        // Do somthing with this rows string, for example to put them in to a list
        listDeclaredElsewhere.Add(myString);
    

【讨论】:

【参考方案2】:
string col1Value = rdr["ColumnOneName"].ToString();

string col1Value = rdr[0].ToString();

这些是objects,因此您需要转换它们或.ToString()

【讨论】:

[] 运算符返回一个对象,您需要将其转换为字符串。 如果您使用 reader.GetString(0) 之类的索引,它将使用您在查询中选择的第一列或表中的第一列。我有一个按顺序包含 3 列的表:ID、Dir、Email。我的命令选择目录和电子邮件。 reader.GetStrting(0) 会检索目录或 ID 吗?索引是基于 SQL Server 上的表本身还是基于您为从表中选择列而执行的查询? @shenk 索引基于您选择参数的顺序。无论哪种方式,您最好使用列名或别名(即 rdr["ID"] 而不是 rdr[0]) @MarkAvenius 过去,通过数字序号进行索引比列名/别名获得了性能改进 - 不确定是否仍然如此 @BaltoStar 很有趣;我没有意识到这一点。但是,根据性能差异(特别是与通过网络推送数据相比,基于您的应用程序),我通常会说查看列名的可读性和可维护性将胜过性能的任何边际改进。谢谢!【参考方案3】:

把从"ColumnName"所在的数据库返回的列的名称开始。如果是字符串,可以使用.ToString()。如果是其他类型,则需要使用System.Convert进行转换。

SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())

    string column = rdr["ColumnName"].ToString();
    int columnValue = Convert.ToInt32(rdr["ColumnName"]);

【讨论】:

【参考方案4】:
while(rdr.Read())

   string col=rdr["colName"].ToString();

会有用的

【讨论】:

toString() is not valid 应该是 .ToString() 仅供参考 @MethodMan 感谢您的信息。我根据您的建议编辑了我的答案。 嗨,我如何将行作为对象而不是按列?例如 id:1,name:'John' 如果我想要下面的东西怎么办。 if(rdr[0]) //在这里做点什么 else if(rdr[1]) //在这里做点什么 【参考方案5】:

想把我的辅助方法分享给那些可以使用它的人:

public static class Sql

    public static T Read<T>(DbDataReader DataReader, string FieldName)
    
        int FieldIndex;
        try  FieldIndex = DataReader.GetOrdinal(FieldName); 
        catch  return default(T); 

        if (DataReader.IsDBNull(FieldIndex))
        
            return default(T);
        
        else
        
            object readData = DataReader.GetValue(FieldIndex);
            if (readData is T)
            
                return (T)readData;
            
            else
            
                try
                
                    return (T)Convert.ChangeType(readData, typeof(T));
                
                catch (InvalidCastException)
                
                    return default(T);
                
            
        
    

用法:

cmd.CommandText = @"SELECT DISTINCT [SoftwareCode00], [MachineID] 
                    FROM [CM_S01].[dbo].[INSTALLED_SOFTWARE_DATA]";
using (SqlDataReader data = cmd.ExecuteReader())

    while (data.Read())
    
        usedBy.Add(
            Sql.Read<String>(data, "SoftwareCode00"), 
            Sql.Read<Int32>(data, "MachineID"));
    

helper方法可以转换成你喜欢的任何值,如果不能转换或者数据库值为NULL,结果将为null。

【讨论】:

一段不错的代码,我将其修改为扩展方法,效果很好reader.GetColumn&lt;int&gt;("M_ID");【参考方案6】:

对于单个结果:

if (reader.Read())

    Response.Write(reader[0].ToString());
    Response.Write(reader[1].ToString());

对于多个结果:

while (reader.Read())

    Response.Write(reader[0].ToString());
    Response.Write(reader[1].ToString());

【讨论】:

【参考方案7】:

我知道这有点老了,但是如果您正在将 SqlDataReader 的内容读入一个类,那么这将非常方便。 reader 和 class 的列名应该相同

public static List<T> Fill<T>(this SqlDataReader reader) where T : new()
        
            List<T> res = new List<T>();
            while (reader.Read())
            
                T t = new T();
                for (int inc = 0; inc < reader.FieldCount; inc++)
                
                    Type type = t.GetType();
                    string name = reader.GetName(inc);
                    PropertyInfo prop = type.GetProperty(name);
                    if (prop != null)
                    
                        if (name == prop.Name)
                        
                            var value = reader.GetValue(inc);
                            if (value != DBNull.Value)
                             
                                prop.SetValue(t, Convert.ChangeType(value, prop.PropertyType), null);
                            
                            //prop.SetValue(t, value, null);

                        
                    
                
                res.Add(t);
            
            reader.Close();

            return res;
        

【讨论】:

这应该是推荐的答案。返回类型列表的非常通用的方法。【参考方案8】:

我会反对在这里使用SqlDataReader; ADO.NET 有很多 边缘情况和复杂情况,根据我的经验,大多数手动编写的 ADO.NET 代码在至少一种方式(通常是微妙的和上下文相关的)中被破坏。

存在避免这种情况的工具。例如,在这种情况下,您想读取一列字符串。 Dapper 使这完全无痛:

var region = ... // some filter
var vals = connection.Query<string>(
    "select Name from Table where Region=@region", // query
    new  region  // parameters
).AsList();

Dapper 在这里处理所有参数化、执行和行处理 - 以及 ADO.NET 的许多其他蹩脚细节。 &lt;string&gt; 可以替换为 &lt;SomeType&gt; 以将整行具体化为对象。

【讨论】:

【参考方案9】:

其实我自己也觉得可以这样:

while (rdr.read())
  
  string str = rdr.GetValue().ToString().Trim();  

【讨论】:

我看不出这种方法比其他方法更复杂。 Trim() 没有在问题中提到,所以在这里,但在其他答案中没有。【参考方案10】:

简单来说,如果您的查询返回 column_name 并且它包含一个字符串:

while (rdr.Read())

    string yourString = rdr.getString("column_name")

【讨论】:

目前阅读器上的.getXXX方法只接受整数序数。【参考方案11】:

我通常通过这种方式通过数据读取器读取数据。只是添加了一个小例子。

string connectionString = "Data Source=DESKTOP-2EV7CF4;Initial Catalog=TestDB;User ID=sa;Password=tintin11#";
string queryString = "Select * from EMP";

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

                using (SqlDataReader reader = command.ExecuteReader())
                
                    if (reader.HasRows)
                    
                        while (reader.Read())
                        
                            Console.WriteLine(String.Format("0, 1", reader[0], reader[1]));
                        
                    
                    reader.Close();
                
            

【讨论】:

【参考方案12】:

我有一个辅助函数,例如:

  public static string GetString(object o)
    
        if (o == DBNull.Value)
            return "";

        return o.ToString();
    

然后我用它来提取字符串:

 tbUserName.Text = GetString(reader["UserName"]);

【讨论】:

Standard Convert.ToString(o) 也一样,因为 DBNull 是 IConvertible,而 DBNull.ToString() 返回 string.Empty。 你是对的,但我不确定我发布此内容时是否这样做。【参考方案13】:

你必须readdatabase column这里。你可以看看下面的代码 sn-p

                string connectionString = ConfigurationManager.ConnectionStrings["NameOfYourSqlConnectionString"].ConnectionString;
                using (var _connection = new SqlConnection(connectionString))
                
                    _connection.Open();

                    using (SqlCommand command = new SqlCommand("SELECT SomeColumnName FROM TableName", _connection))
                    

                        SqlDataReader sqlDataReader = command.ExecuteReader();
                        if (sqlDataReader.HasRows)
                        
                            while (sqlDataReader.Read())
                            
                                string YourFirstDataBaseTableColumn = sqlDataReader["SomeColumn"].ToString(); // Remember Type Casting is required here it has to be according to database column data type
                                string YourSecondDataBaseTableColumn = sqlDataReader["SomeColumn"].ToString();
                                string YourThridDataBaseTableColumn = sqlDataReader["SomeColumn"].ToString();

                            
                        
                        sqlDataReader.Close();
                    
                    _connection.Close();

【讨论】:

以上是关于从 SqlDataReader 读取数据的主要内容,如果未能解决你的问题,请参考以下文章

C#利用SqlDataReader读取SQL Server数据表

SqlDataReader 读取方法不起作用

如果 SqlDataAdapter 内部使用数据读取器,为啥人们说使用 SqlDataReader 更快?

使用Visual Studio自带数据库配合SqlDataReader 读取数据库数据

SqlDataReader

SqlDataReader