Что такое хороший способ разбиения на страницы с ASP.NET MVC2 + LINQ-to-Entities? - PullRequest
0 голосов
/ 17 ноября 2010

Я создал внутренний веб-сайт, который использует большое количество данных из базы данных SQL (на данный момент 1 282 727 строк (~ 800 МБ), растет каждую минуту), я использую этот код (LINQ для сущностей) для отображения страницы с нумерацией страниц:

    public ActionResult Index(int page = 0)
    {
        IronViperEntities db = new IronViperEntities();
        db.Connection.Open();
        DbTransaction transaction = db.Connection.BeginTransaction(IsolationLevel.ReadUncommitted);
        var messages = (from globalView in db.GlobalViews orderby globalView.MessageId descending select globalView).Skip(page*perPage).Take(perPage);
        transaction.Commit();
        db.Connection.Close();
        ViewData["page"] = page;
        ViewData["messages"] = messages;
        return View();
    }

Все работает нормально, за исключением того, что выглядит больше, если номер страницы, медленнее страница, когда я показываю страницу 2, это занимает ~ 700 мс (90% от задержки), когда я показываю страницу 6354, это занимает 4280 мс ...

Это нормально? Если нет, то как это исправить?

Веб-сайт использует ASP.NET MVC2, Windows Server 2008 R2 Enterprise Edition, SQL Server 2008 R2 Express Edition.

РЕДАКТИРОВАТЬ: Вот пример SQL-запроса, сгенерированного LINQ To Entities:

SELECT TOP (100) 
[Extent1].[MessageId] AS [MessageId], 
[Extent1].[MessageUuid] AS [MessageUuid], 
[Extent1].[MessageData] AS [MessageData], 
[Extent1].[MessagePostDate] AS [MessagePostDate], 
[Extent1].[ChannelName] AS [ChannelName], 
[Extent1].[UserName] AS [UserName], 
[Extent1].[UserUuid] AS [UserUuid], 
[Extent1].[ChannelUuid] AS [ChannelUuid]
FROM ( SELECT [Extent1].[MessageId] AS [MessageId], [Extent1].[MessageUuid] AS 
[MessageUuid],     [Extent1].[MessageData] AS [MessageData], [Extent1].[MessagePostDate] AS
[MessagePostDate], [Extent1].[ChannelName] AS [ChannelName], [Extent1].[UserName] AS [UserName],
[Extent1].[UserUuid] AS [UserUuid], [Extent1].[ChannelUuid] AS [ChannelUuid], row_number() OVER
(ORDER BY [Extent1].[MessageId] DESC) AS [row_number]
FROM (SELECT 
  [GlobalView].[MessageId] AS [MessageId], 
  [GlobalView].[MessageUuid] AS [MessageUuid], 
  [GlobalView].[MessageData] AS [MessageData], 
  [GlobalView].[MessagePostDate] AS [MessagePostDate], 
  [GlobalView].[ChannelName] AS [ChannelName], 
  [GlobalView].[UserName] AS [UserName], 
  [GlobalView].[UserUuid] AS [UserUuid], 
  [GlobalView].[ChannelUuid] AS [ChannelUuid]
  FROM [dbo].[GlobalView] AS [GlobalView]) AS [Extent1]
)  AS [Extent1]
WHERE [Extent1].[row_number] > 656700
ORDER BY [Extent1].[MessageId] DESC

1 Ответ

0 голосов
/ 17 ноября 2010

Часть вашей проблемы в том, что вы создаете транзакцию БД для операции только для чтения, как сказал Кирк Волл в ваших комментариях.Другой вопрос: почему вы открываете соединение БД?Похоже, вы используете Entity Framework, что означает, что вам ничего не нужно.Просто используйте операцию «Только чтение» для заполнения объекта и затем вызовите object.SaveChanges ();Это сохранит изменения обратно в базу данных.Например:

MyProjectEntities db = new MyProjectEntities();
Person person = db.People.Where(x => x.Name == "John Doe").First();
person.Name = "ChangedObjectData";
db.SaveChanges();

Измените свой метод действия так, чтобы он выглядел следующим образом, и скажите мне, если он все еще выполняет то, что вы ищете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...