2015-02-19 8 views
5

Próbuję zastosować paginację do mojej aplikacji MVC. Iam użyciu Azure przechowywanie tabeliDodawanie tabelarycznego przechowywania tabel MVC i Azure

Oto co próbowałem: -

public List<T> GetPagination(string partitionKey, int start, int take) 
    { 
     List<T> entities = new List<T>(); 

     TableQuery<T> query = new TableQuery<T>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey.ToLower())); 
     entities = Table.ExecuteQuery(query).Skip(start).Take(take).ToList(); 

     return entities; 

    } 

Kontroler: -

public ActionResult Index() 
     { 

      key= System.Web.HttpContext.Current.Request[Constants.Key]; 
      if (String.IsNullOrEmpty(key)) 
       return RedirectToAction("NoContext", "Error"); 

      var items= _StorageHelper.GetPagination(key,0,3); 
      ItemCollection itemCollection = new ItemCollection(); 
      itemCollection .Items= Mapper.Map<List<ItemChart>, List<ItemModel>>(items); 
      itemCollection .Items.ForEach(g => g.Object = g.Object.Replace(key, "")); 


      return View(itemCollection); 
     } 

to obecnie daje mi 3 pierwsze wpisy z moimi danymi. Jak mogę teraz pokazać i zaimplementować "Poprzedni" i "Następny", aby wyświetlić pozostałe wpisy na następnej stronie? Jak zaimplementować resztę kontrolera i stronę HTML?

Każda pomoc jest doceniana.

Odpowiedz

12

Jeśli chodzi o paginacji, istnieje kilka rzeczy do rozważenia:

  • Nie wszyscy operatorzy LINQ (aw opcji zapytań OData obrotu) są obsługiwane przez Table Service. Na przykład Skip nie jest obsługiwany. Listę obsługiwanych operatorów można znaleźć pod następującym linkiem: https://msdn.microsoft.com/en-us/library/azure/dd135725.aspx.
  • Sposób dzielenia stron na usługę tabelaryczną polega na tym, że podczas wysyłania zapytania do tabeli w celu pobrania niektórych danych maksymalna liczba jednostek, które mogą zostać zwrócone przez usługę tabeli, wynosi 1000. Nie ma gwarancji, że zawsze zwróci się 1000 jednostek. Może być mniejszy niż 1000 lub nawet 0 w zależności od tego, jak pytasz. Jeśli jednak dostępnych jest więcej wyników, usługa tabeli zwraca coś, co nazywa się Continuation Token. Token ten należy wykorzystać do pobrania następnego zestawu wyników z usługi tabeli. Zobacz ten link, aby uzyskać więcej informacji na temat limitu czasu zapytania i podziału na strony: https://msdn.microsoft.com/en-us/library/azure/dd135718.aspx.

Biorąc pod uwagę te dwa czynniki, nie można naprawdę zaimplementować rozwiązania stronicowania, w którym użytkownik może bezpośrednio przejść do określonej strony (na przykład użytkownik siedzi na stronie 1, a użytkownik nie może przejść do strony 4). Co najwyżej możesz zaimplementować funkcje następnej strony, poprzedniej strony i pierwszej strony.

Aby zaimplementować rodzaj funkcjonalności next page, przechowuj token kontynuacji zwracany przez usługę tabeli i używaj go w zapytaniu.

Aby zaimplementować rodzaj funkcjonalności previous page, należy przechowywać wszystkie tokeny kontynuacji zwrócone w tablicy lub czymś i śledzić stronę, na której aktualnie znajduje się użytkownik (taki byłby bieżący indeks strony). Gdy użytkownik chce przejść do poprzedniej strony, otrzymuje się token kontynuacji dla poprzedniego indeksu (tj. Bieżący indeks strony - 1) i używa go w zapytaniu.

Aby zaimplementować rodzaj funkcjonalności first page, wystarczy wysłać zapytanie bez tokena kontynuacji.

Jeśli chcesz zaimplementować podział na strony, zapoznaj się z metodą ExecuteQuerySegmented w bibliotece klienta pamięci masowej.

UPDATE

proszę zobaczyć przykładowy kod poniżej. Dla uproszczenia zachowałem tylko pierwszą stronę i funkcjonalność następnej strony:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using Microsoft.WindowsAzure.Storage.Auth; 
using Microsoft.WindowsAzure.Storage.Blob; 
using Microsoft.WindowsAzure.Storage; 
using Microsoft.WindowsAzure.Storage.Queue; 
using Microsoft.WindowsAzure.Storage.Table; 
namespace TablePaginationSample 
{ 
    class Program 
    { 
     static string accountName = ""; 
     static string accountKey = ""; 
     static string tableName = ""; 
     static int maxEntitiesToFetch = 10; 
     static TableContinuationToken token = null; 
     static void Main(string[] args) 
     { 
      var cloudStorageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true); 
      var cloudTableClient = cloudStorageAccount.CreateCloudTableClient(); 
      var table = cloudTableClient.GetTableReference(tableName); 
      Console.WriteLine("Press \"N\" to go to next page\nPress \"F\" to go first page\nPress any other key to exit program"); 
      var query = new TableQuery().Take(maxEntitiesToFetch); 
      var continueLoop = true; 
      do 
      { 
       Console.WriteLine("Fetching entities. Please wait...."); 
       Console.WriteLine("-------------------------------------------------------------"); 
       var queryResult = table.ExecuteQuerySegmented(query, token); 
       token = queryResult.ContinuationToken; 
       var entities = queryResult.Results; 
       foreach (var entity in entities) 
       { 
        Console.WriteLine(string.Format("PartitionKey = {0}; RowKey = {1}", entity.PartitionKey, entity.RowKey)); 
       } 
       Console.WriteLine("-------------------------------------------------------------"); 
       if (token == null)//No more token available. We've reached end of table 
       { 
        Console.WriteLine("All entities have been fetched. The program will now terminate."); 
        break; 
       } 
       else 
       { 
        Console.WriteLine("More entities available. Press \"N\" to go to next page or Press \"F\" to go first page or Press any other key to exit program."); 
        Console.WriteLine("-------------------------------------------------------------"); 
        var key = Console.ReadKey(); 
        switch(key.KeyChar) 
        { 
         case 'N': 
         case 'n': 
          continue; 
         case 'F': 
         case 'f': 
          token = null; 
          continue; 
         default: 
          continueLoop = false; 
          break; 
        } 
       } 
      } while (continueLoop); 
      Console.WriteLine("Press any key to terminate the application."); 
      Console.ReadLine(); 
     } 
    } 
} 
+0

Dziękuję za odpowiedź. Jestem całkiem nowy w tej koncepcji. Czy możesz mi wyjaśnić to na przykładzie? – HappyCode1990

+0

Zaktualizowałem moją odpowiedź za pomocą przykładowego kodu. Proszę spojrzeć. HTH. –

+1

Należy zauważyć, że to rozwiązanie nie zawsze działa tak, jak masz nadzieję. Jeśli zapytanie trwa dłużej niż 5 sekund, otrzymasz wynik mniejszy niż maksymalny wynik ORAZ znacznik kontynuacji. Mam podobne rozwiązanie zaimplementowane w mojej aplikacji i czasami dostaję puste strony i muszę kilkakrotnie nacisnąć "Dalej", aby uzyskać pierwsze wyniki. – Mike