C# недопустимая попытка вызова Read при закрытии reader
у меня есть недопустимая попытка вызвать Read, когда reader закрыт ошибка, когда я делаю проект 3 уровня на языке C#. Я пытаюсь получить столбец адресных данных, объединив две таблицы вместе и отобразив их в раскрывающемся списке. Вот мой уровень доступа к данным:
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;
}
2 ответов
это не работает, потому что вы закрываете соединение перед возвратом считывателя. Читатель работает только тогда, когда соединение открыто:
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;
}
предыдущий-хороший пример ... Но вы также можете выполнить это ниже кода, который является automatically
закрыть connection
при datareader.close()
метод называется ...
reader = Sqlcmd.ExecuteReader(CommandBehavior.CloseConnection);