当我用C#语言做三层项目时,当阅读器关闭时,我调用Read的尝试无效错误。我想做的是通过将两个表连接在一起并显示在下拉列表中来检索地址数据列。这是我的数据访问层:
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;
}
它不起作用,因为您在返回读取器之前关闭了连接。读卡器仅在连接打开时工作:
result = command.ExecuteReader();
connection.Close();
return result; // here the reader is not valid
一般来说,您不应该将阅读器返回到业务层。读卡器只能在数据访问层中使用。应该使用它,然后关闭它和连接。
您应该返回一个在连接关闭后可以工作的对象,例如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;
}
上一个就是一个很好的例子。。。但您也可以通过以下代码来实现,即当datareader.close()
方法调用时,automatically
关闭connection
实例。。。
reader = Sqlcmd.ExecuteReader(CommandBehavior.CloseConnection);