在foreach循环中声明时的SQLDataReader对象

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在foreach循环中声明时的SQLDataReader对象相关的知识,希望对你有一定的参考价值。

这是我不时回到的,但还没有找到明确的答案。希望我能在微软保留语言之前得到它(开玩笑......有点)......

这几乎肯定是错的,但这就是我从SQLServer中检索记录的方式......我将每行传递给它的调用者作为IDataRecord并使用SQLDataREader对象来迭代它。我已经读过,如果没有在using语句中声明,应该在使用后关闭datareader。我应该关闭这个吗?

我的SQLDataReader在这样的foreach循环中声明...

    IEnumerable<IDataRecord> dataset = Select("SELECT Topic FROM Topics WHERE pti=" + pid + " and Ignore = 0");
foreach (SqlDataReader reader in dataset )
{
     string topic = reader.GetString(0);
    //... do something
}

我的db调用:

public IEnumerable<IDataRecord> Select(string sql, List<SqlParameter> sparams = null)
{
    using (SqlConnection cn = new SqlConnection(ConnString()))
    {
        cn.Open();

        using (SqlCommand cmd = new SqlCommand(sql, cn))
        {
            if (sparams != null)
            {
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.AddRange(sparams.ToArray());
            }
            else
            {
                cmd.CommandType = CommandType.Text;
            }

            using (SqlDataReader rdr = cmd.ExecuteReader())
            {
                if (rdr != null && rdr.FieldCount > 0)
                {
                    while (rdr.Read())
                    {
                        yield return rdr;
                    }
                }

            }
        }

        cn.Close();

    }
}
答案

实际上没有什么可以关闭的。代码中的可关闭阅读器对象是使用连接的对象,但它会被using方法中的Select语句自动关闭。

我认为你这样做的方式非常罕见。如果你能够改变方法签名,你可以通过做一个List<>简单地返回一个cast,然后像这样删除yield

    public List<IDataRecord> Select(string sql , List<SqlParameter> sparams = null)
        {                                                                          
            using (SqlConnection cn = new SqlConnection (ConnectionString))          
            {                                                                        
                cn.Open ( );                                                           

                using (SqlCommand cmd = new SqlCommand (sql , cn))                     
                {                                                                      
                    if (sparams != null)                                                 
                    {                                                                    
                        cmd.CommandType = CommandType.StoredProcedure;                     
                        cmd.Parameters.AddRange (sparams.ToArray ( ));                     
                    }                                                                    
                    else                                                                 
                    {                                                                    
                        cmd.CommandType = CommandType.Text;                                
                    }                                                                    

                    using (SqlDataReader rdr = cmd.ExecuteReader ( ))                    
                    {                                                                    
                        return rdr.Cast<IDataRecord> ( ).ToList ( );                       

                    }                                                                    
                }                                                                      
            }                                                                        
        } 

我在数据库连接类中完成了这个。这很简单,但如果您有任何疑问,请发表评论:

using System;                                                                                                                                                      
using System.Collections.Generic;                                                                                                                                  
using System.Data;                                                                                                                                                 
using System.Data.SqlClient;                                                                                                                                       
using System.Linq;                                                                                                                                                 

namespace SqlToDb                                                                                                                                                  
{                                                                                                                                                                  
    public class SqlClientData                                                                                                                                       
    {                                                                                                                                                                
        private string connectionstring;                                                                                                                               

        public string ConnectionString { get => connectionstring; set => connectionstring = value; }                                                                   

        public SqlClientData(string connection_string)                                                                                                                 
        {                                                                                                                                                              
            ConnectionString = connection_string;                                                                                                                        
        }                                                                                                                                                              

        public T ExecuteScalar<T>(string queryString)                                                                                                                  
        {                                                                                                                                                              
            using (SqlConnection conn = new SqlConnection (ConnectionString))                                                                                            
            {                                                                                                                                                            

                using (SqlCommand cmd = new SqlCommand (queryString , conn))                                                                                               
                {                                                                                                                                                          
                    try                                                                                                                                                      
                    {                                                                                                                                                        
                        conn.Open ( );                                                                                                                                         
                        var result = cmd.ExecuteScalar ( );                                                                                                                    

                        if (Convert.IsDBNull (result) && typeof (T).IsValueType)                                                                                               
                            return default (T);                                         // if the db value is null, but T is a value type, set T = the default value of the type.
                        else                                                                                                                                                   
                            return (T) (result);                                                                                                                                 
                    }                                                                                                                                                        
                    finally                                                                                                                                                  
                    {                                                                                                                                                        
                        conn.Close ( );                                                                                                                                        
                    }                                                   

以上是关于在foreach循环中声明时的SQLDataReader对象的主要内容,如果未能解决你的问题,请参考以下文章

foreach循环上的PowerShell + =添加重复的实例

完成foreach循环后如何在节点js中返回推送的数组响应?

C# 使用IEnumerable,yield 返回结果,同时使用foreach时,在循环内修改变量的值无效

foreach用法

foreach用法

Mybatis 循环删除/插入