在foreach循环

时间:2017-12-10 04:34:52

标签: garbage-collection 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
}

我的数据库电话:

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

    }
}

1 个答案:

答案 0 :(得分:1)

实际上没有什么可以关闭的。代码中的可关闭阅读器对象是使用该连接的对象,但它会被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 ( );                                                                                                                                        
                    }                                                                                                                                                        

                }                                                                                                                                                          

            }                                                                                                                                                            
        }                                                                                                                                                              

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

    }                                                                                                                                                                
}