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

SQLDataReader object when declared in a foreach loop

这是我不时return的问题,但还没有找到明确的答案。希望我能在微软继承这门语言之前得到它(开玩笑……有点)……

这几乎肯定是错误的,但这就是我从 SQLServer 检索记录的方式...我将每一行作为 IDataRecord 传递给它的调用者,并使用 SQLDataREader 对象遍历它。我读过,如果未在 using 语句中声明,则应在使用后关闭数据读取器。我应该关闭这个吗?

我的 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
}

我的数据库调用:

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();

    }
}

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

我认为你这样做的方式很不常见。如果您能够更改方法签名,则可以通过执行 cast 并像这样删除 yield 来简单地 return a List<>

    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 ( );                       

                    }                                                                    
                }                                                                      
            }                                                                        
        } 

我已经在数据库连接中完成了此操作 class。这非常简单,但是 post 如果您有任何问题,请发表评论:

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 ( );                                                                                                                                        
                    }                                                                                                                                                        

                }                                                                                                                                                          

            }                                                                                                                                                            
        }                                                                                                                                                              

        public List<T> ExecScalarList<T>(string sql , bool exclude_nulls , bool replace_null_with_default)                                                             
        {                                                                                                                                                              
            using (SqlConnection conn = new SqlConnection (ConnectionString))                                                                                            
            {                                                                                                                                                            
                using (SqlCommand cmd = new SqlCommand (sql , conn))                                                                                                       
                {                                                                                                                                                          
                    conn.Open ( );                                                                                                                                           
                    using (SqlDataReader rdr = cmd.ExecuteReader ( ))                                                                                                        
                    {                                                                                                                                                        
                        var mylist = new List<T> { };                                                                                                                          
                        while (rdr.Read ( ))                                                                                                                                   
                        {                                                                                                                                                      
                            if (!Convert.IsDBNull (rdr[0]) || (exclude_nulls == false && replace_null_with_default == false))                                                    
                            {                                                                                                                                                    
                                mylist.Add ((T) Convert.ChangeType (rdr[0] , typeof (T)));                                                                                         
                            }                                                                                                                                                    
                            else                                                                                                                                                 
                            {                                                                                                                                                    
                                if (exclude_nulls == false)                                                                                                                        
                                {                                                                                                                                                  
                                    if (replace_null_with_default == true) mylist.Add (default (T));   // returns the default for the type... not null                               
                                }                                                                                                                                                  
                            }                                                                                                                                                    
                        }                                                                                                                                                      

                        return mylist;                                                                                                                                         

                    }                                                                                                                                                        
                }                                                                                                                                                          
            }                                                                                                                                                            
        }                                                                                                                                                              

        public List<IDataRecord> ExecReader(string sql)                                                                                                                
        {                                                                                                                                                              
            using (SqlConnection conn = new SqlConnection (ConnectionString))                                                                                            
            {                                                                                                                                                            
                using (SqlCommand cmd = new SqlCommand (sql , conn))                                                                                                       
                {                                                                                                                                                          
                    conn.Open ( );                                                                                                                                           
                    using (SqlDataReader rdr = cmd.ExecuteReader ( ))                                                                                                        
                    {                                                                                                                                                        
                        return rdr.Cast<IDataRecord> ( ).ToList ( );                                                                                                           

                    }                                                                                                                                                        
                }                                                                                                                                                          
            }                                                                                                                                                            
        }                                                                                                                                                              

        public int ExecNonQuery(string sql)                                                                                                                            
        {                                                                                                                                                              
            int result = 0;                                                                                                                                              
            using (SqlConnection cn = new SqlConnection (ConnectionString))                                                                                              
            {                                                                                                                                                            
                using (SqlCommand cmd = new SqlCommand (sql , cn))                                                                                                         
                {                                                                                                                                                          
                    cmd.CommandType = CommandType.Text;  // or CommandType.StoredProcedure                                                                                   
                    cn.Open ( );                                                                                                                                             

                    try                                                                                                                                                      
                    {                                                                                                                                                        
                        result = (Int32) cmd.ExecuteNonQuery ( );               //returns the number of rows affected                                                          
                    }                                                                                                                                                        
                    finally                                                                                                                                                  
                    {                                                                                                                                                        
                        cn.Close ( );                                                                                                                                          
                    }                                                                                                                                                        

                }                                                                                                                                                          
            }                                                                                                                                                            
            return result;                                                                                                                                               
        }                                                                                                                                                              

    }                                                                                                                                                                
}