Пейджинг данных в SQL Server CE (Compact Edition)
Я пишу приложение для удаления wpf и хотел бы использовать SQL Server CE в качестве бэкэнд. Я пытаюсь придумать хороший способ сделать эффективный пейджинг данных. В SQL Server Express я могу сделать что-то вроде этого:
Select ID, FirstName, LastName
From (SELECT ROW_NUMBER() OVER (ORDER BY ID)
AS Row, ID, FirstName, LastName
From TestTable
)
WHERE Row > 1 AND Row <= 10
Есть ли что-то сопоставимое в SQL Server CE? Я не совсем уверен, что есть и не поддерживается. Я хочу только возвращать 10 строк за раз из базы данных и не возвращать все данные, а затем фильтровать их для отображения пользователю, так как это намного медленнее. Спасибо.
Ответы
Ответ 1
Честно говоря, возможно, самое быстрое, что нужно сделать, это использовать SqlCeDataReader и вызвать .Read() 10 раз. Затем, когда пользователь переходит к следующей странице, вы уже указываете на 11-й результат и можете читать еще 10. Если вам нужно вернуться назад, вы можете либо кэшировать свои результаты, либо переключиться на SqlCeResultSet, который поддерживает поиск.
Кроме того, SqlCeDataReader/Result - это, по опыту, самый быстрый способ взаимодействия с базой данных на рабочем столе. Это может быть буквально в 100 раз быстрее, чем использование DataSets/DataAdapters.
Ответ 2
В случае, если кто-то дойдет до этой страницы, ища ответ...
Я столкнулся с этим сообщением: поддержка запросов подкачки в SQL Server CE 4.0
http://beyondrelational.com/blogs/jacob/archive/2010/07/13/support-for-paging-queries-in-sql-server-ce-4-0.aspx
Надеюсь, что это поможет
Ответ 3
В настоящее время я работаю над WPF-приложением, которое использует SQL Server CE как механизм сохранения. У нас есть несколько (40+) таблиц, и некоторые из них довольно большие (50 тыс. Записей, по крайней мере, для моих стандартов).
Мой совет по обработке данных непосредственно в SQL CE: избегайте этого, если вы можете! Я использовал подход, описанный Бобом Кингом, и, по крайней мере, для меня это привело к очень уродливому коду, кошмару реального обслуживания.
Если вам не нужно будет печатать более десятков тысяч записей, я считаю, что лучший способ - загрузить их все, используя SqlCeDataReader в коллекцию пользовательских классов, а затем страницу по коллекции в памяти. Я нашел этот подход более отзывчивым, чем повторное выполнение SQL-запроса каждый раз, даже при кешировании. Случилось так, что в моем случае запросы были довольно сложными, и производительность SqlCeDataReader была достаточно хороша, так что удар производительности был почти незаметен. Не нужно указывать, что после первой пакетной загрузки каждое изменение страницы происходит почти мгновенно, потому что все хранится в памяти.
Общее мнение моих пользователей заключалось в том, что дождаться, пока первые результаты появятся, будет немного дольше, если это приведет к более быстрому поисковому вызову. И используя LINQ, поисковый вызов так же прост, как вызов методов Skip и Take. Я реализовал эту логику внутри Pager <T> класс, делая его очень сухим и приятным.
Ответ 4
Существует несколько способов, но наиболее упрощенным способом было бы следующее:
Предполагая
- Размер страницы = 10
- Страница = 2
Тогда
- Первый TOP = PageSize (10)
- Второй TOP = PageSize * Page (20)
SELECT
[Page].[ID],
[Page].[FirstName],
[Page].[LastName]
FROM
(
SELECT TOP (10)
[FirstRows].[ID],
[FirstRows].[FirstName],
[FirstRows].[LastName]
FROM
(
SELECT TOP (20)
[TestTable].[ID],
[TestTable].[FirstName],
[TestTable].[LastName]
FROM
[TestTable]
ORDER BY
[TestTable].[ID] ASC
) AS [FirstRows]
ORDER BY
[FirstRows].[ID] DESC
) AS [Page]
ORDER BY
[Page].[ID] ASC
Ответ 5
Я реализовал пользовательский пейджинг для datagrid с использованием SQL CE. Я реализовал метод использования команды top в select и пропущенных записей с использованием подзапроса, как описано в приведенном выше ответе. Но он работает хорошо с небольшим количеством данных. Поскольку показатели растут в тысячах, вышеуказанная методология становится менее полезной и замедляется в производительности.
Я решил проблему с низкой производительностью, используя мою собственную технику. Что я сделал - я храню идентификатор первой и последней записи на каждой странице в переменных.
dim firstRecord=dt.rows(0)("id")
и
dim lastRecord=dt.Rows(dt.rows.count-1)("id")
Я инициализирую эти переменные после привязки сетки для каждой страницы.
Если пользователь нажмет следующую кнопку, я заберу записи верхнего уровня (Pagsize) из базы данных, большей, чем lastRecord
Если пользователь нажимает на предыдущую кнопку, я выбираю записи верхнего уровня (PageSize) из базы данных меньше, чем firstRecord. Также я заказываю Id в этом случае. И измените порядок данных, используя dataview до asc, перед привязкой к datagrid.
Это сделало мой пейджинг наиболее эффективным. Хотя мне пришлось приложить дополнительные усилия для вставки и удаления записей. Но я смог справиться с этим.