在 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;
}
}
}
这是我不时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;
}
}
}