当阅读器关闭时,C# 尝试调用 Read 无效
Posted
技术标签:
【中文标题】当阅读器关闭时,C# 尝试调用 Read 无效【英文标题】:C# Invalid attempt to call Read when reader is closed 【发布时间】:2013-12-26 12:28:13 【问题描述】:当我使用 C# 语言进行 3 层项目时,我在阅读器关闭时尝试调用读取错误。 我要做的是通过将两个表连接在一起并显示在下拉列表中来检索地址数据列。 这是我的数据访问层:
public List<Distribution> getDistributionAll()
List<Distribution> distributionAll = new List<Distribution>();
string address;
SqlDataReader dr = FoodBankDB.executeReader("SELECT b.addressLineOne FROM dbo.Beneficiaries b INNER JOIN dbo.Distributions d ON d.beneficiary = b.id");
while (dr.Read())
address = dr["addressLineOne"].ToString();
distributionAll.Add(new Distribution(address));
return distributionAll;
这是我的 FoodBankDB 课程:
public class FoodBankDB
public static string connectionString = Properties.Settings.Default.connectionString;
public static SqlDataReader executeReader(string query)
SqlDataReader result = null;
System.Diagnostics.Debug.WriteLine("FoodBankDB executeReader: " + query);
SqlConnection connection = new SqlConnection(connectionString);
SqlCommand command = new SqlCommand(query, connection);
connection.Open();
result = command.ExecuteReader();
connection.Close();
return result;
我将它们分成两个类,这样每当我的连接字符串发生变化时,我都可以通过更改 FoodBankDB 类轻松修改整个项目。
这是我的业务逻辑层:
public List<Distribution> getAllScheduledDistribution()
List<Distribution> allDistribution = new List<Distribution>();
Distribution distributionDAL = new Distribution();
allDistribution = distributionDAL.getDistributionAll();
return allDistribution;
最后但同样重要的是,我的表示层:
List<Distribution> scheduledList = new List<Distribution>();
scheduledList = packBLL.getAllScheduledDistribution();
ddlScheduleList.DataSource = scheduledList;
ddlScheduleList.DataTextField = "address";
ddlScheduleList.DataValueField = "address";
ddlScheduleList.DataBind();
如果我不拆分数据访问层和连接字符串类,它工作得很好。有人知道如何解决这个错误吗?
提前致谢。
更新部分
public static string GetConnectionString()
return connectionString;
【问题讨论】:
【参考方案1】:它不起作用,因为您在返回阅读器之前关闭了连接。阅读器仅在连接打开时工作:
result = command.ExecuteReader();
connection.Close();
return result; // here the reader is not valid
一般来说,您不应该将阅读器返回到业务层。 Reader 只能用于数据访问层。它应该被使用,然后它和连接应该被关闭。
您应该返回一个在连接关闭后可以工作的对象,例如DataSet
或 DataTable
或 DTO 的集合。例如:
public List<Distribution> getDistributionAll()
List<Distribution> distributionAll = new List<Distribution>();
using (var connection = new SqlConnection(FoodBankDB.GetConnectionString())) // get your connection string from the other class here
SqlCommand command = new SqlCommand("SELECT b.addressLineOne FROM dbo.Beneficiaries b INNER JOIN dbo.Distributions d ON d.beneficiary = b.id", connection);
connection.Open();
using (var dr = command.ExecuteReader())
while (dr.Read())
string address = dr["addressLineOne"].ToString();
distributionAll.Add(new Distribution(address));
return distributionAll;
【讨论】:
你介意给我看一些关于如何解决这个问题的例子吗?因为我有点困惑 见上面的例子。我希望没有小错误,因为我现在无法运行代码。 我应该将 GetConnectionString() 编码为更新部分吗?还是我做错了? 是的,在上面的代码中,你需要 GetConnectionString() 编码。或者,你可以直接使用 FoodBankDB.connectionString: using (var connection = new SqlConnection(FoodBankDB.connectionString)) ... . 是的,没错。正如你所说的那样,我就是这样做的。【参考方案2】:上一个是一个很好的例子......但是你也可以通过下面的代码来完成它,即automatically
close a connection
instance when datareader.close()
method called ...
reader = Sqlcmd.ExecuteReader(CommandBehavior.CloseConnection);
【讨论】:
很抱歉在一个非常旧的帖子上发帖,但我想知道您是否绝对有必要致电datareader.close()
来关闭连接?用CommandBehavior.CloseConnection
初始化实例后不会自动处理
@hiFI .. 不,它不会。由于数据读取器在打开连接上工作..并且可以有多个结果集..所以您需要显式关闭数据读取器...上述参数的好处是它也会调用相关连接来关闭
不管怎么说,你的解决方案是救世主!这比将连接作为out
参数传递更容易。谢谢以上是关于当阅读器关闭时,C# 尝试调用 Read 无效的主要内容,如果未能解决你的问题,请参考以下文章