Как получить количество строк с помощью SqlDataReader в C#
мой вопрос заключается в том, как получить количество строк, возвращаемых запросом с помощью SqlDataReader
в C#. Я видел некоторые ответы об этом, но ни один из них не был четко определен, за исключением того, что государства делают цикл while с Read()
метод и инкремент счетчика.
моя проблема заключается в том, что я пытаюсь заполнить многомерный массив с первой строки заголовков столбцов и всех строк после этого данные строки.
Я знаю, что я могу просто выбросить в Список управления и не беспокоиться об этом, но для моего личного назидания, и я также хотел бы вытащить данные в массив и из массива, как я выбираю и отображать его в разных форматах.
так что я думаю, что я не могу сделать Read()
а затем инкремент ++ путь, потому что это означает, что мне придется открыть Read()
а потом открыть Read()
снова, чтобы получить количество строк, а затем столбцов данных.
просто небольшой пример того, о чем я говорю:
int counter = 0;
while (sqlRead.Read())
{
//get rows
counter++
}
и затем a для цикл для запуска через столбцы и поп
something.Read();
int dbFields = sqlRead.FieldCount;
for (int i = 0; i < dbFields; i++)
{
// do stuff to array
}
6 ответов:
есть только два варианта:
узнайте, прочитав все строки (а затем вы можете также хранить их)
предварительно выполните специализированный запрос SELECT COUNT (*).
дважды пройти через цикл DataReader действительно дорого, вам придется повторно выполнить запрос.
и (спасибо Питу OHanlon) второй вариант-это многопоточность-безопасная при использовании транзакции со снимком уровень изоляции.
Так как вы хотите в конечном итоге хранить все строки в памяти в любом случае единственным разумным вариантом является чтение всех строк в гибком хранилище (
List<>
илиDataTable
), а затем скопируйте данные в любой формат, который вы хотите. Работа в памяти всегда будет намного эффективнее.
реляционные классы / набор данных - Это подходящий вариант.
using (DataTable dt = new DataTable()) { dt.Load(sqlRead); Console.WriteLine(dt.Rows.Count); }
выше, набор данных или типизированный набор данных может быть хорошей временной структурой, которую вы можете использовать для фильтрации. SqlDataReader предназначен для чтения данных очень быстро. Пока вы находитесь в цикле while (), вы все еще подключены к БД, и он ждет вас, чтобы сделать все, что вы делаете, чтобы прочитать/обработать следующий результат, прежде чем он двинется дальше. В этом случае вы можете получить лучшую производительность, если вы вытащите все данные, закройте соединение с БД и обработайте результаты "автономный."
люди, кажется, ненавидят наборы данных, так что выше может быть сделано с коллекцией строго типизированных объектов, а также.
Если вам не нужно извлекать всю строку и вы хотите избежать двойного запроса, вы, вероятно, можете попробовать что-то вроде этого:
using (var sqlCon = new SqlConnection("Server=127.0.0.1;Database=MyDb;User Id=Me;Password=glop;")) { sqlCon.Open(); var com = sqlCon.CreateCommand(); com.CommandText = "select * from BigTable"; using (var reader = com.ExecuteReader()) { //here you retrieve what you need } com.CommandText = "select @@ROWCOUNT"; var totalRow = com.ExecuteScalar(); sqlCon.Close(); }
возможно, вам придется добавить транзакцию, не уверенную, что повторное использование той же команды автоматически добавит транзакцию на нее...
вы не можете получить количество строк непосредственно из устройства чтения данных, потому что это то, что известно как курсор firehose - что означает, что данные считываются по строкам на основе выполняемого чтения. Я бы посоветовал не делать 2 чтения данных, потому что есть потенциал, что данные изменились между выполнением 2 чтения, и, таким образом, вы получите разные результаты.
Что вы можете сделать, это прочитать данные во временную структуру, и использовать в место второго чтения. Кроме того, вам нужно будет изменить механизм, с помощью которого вы получаете данные, и вместо этого использовать что-то вроде DataTable.
Я также сталкиваюсь с ситуацией, когда мне нужно было вернуть верхний результат, но также хотел получить общие строки, которые соответствуют запросу. я наконец добираюсь до этого решения:
public string Format(SelectQuery selectQuery) { string result; if (string.IsNullOrWhiteSpace(selectQuery.WherePart)) { result = string.Format( @" declare @maxResult int; set @maxResult = {0}; WITH Total AS ( SELECT count(*) as [Count] FROM {2} ) SELECT top (@maxResult) Total.[Count], {1} FROM Total, {2}", m_limit.To, selectQuery.SelectPart, selectQuery.FromPart); } else { result = string.Format( @" declare @maxResult int; set @maxResult = {0}; WITH Total AS ( SELECT count(*) as [Count] FROM {2} WHERE {3} ) SELECT top (@maxResult) Total.[Count], {1} FROM Total, {2} WHERE {3}", m_limit.To, selectQuery.SelectPart, selectQuery.FromPart, selectQuery.WherePart); } if (!string.IsNullOrWhiteSpace(selectQuery.OrderPart)) result = string.Format("{0} ORDER BY {1}", result, selectQuery.OrderPart); return result; }