2013-02-05 9 views
6

Pracuję w sklepie internetowym, takim jak strona asp.net mvc 4 z serwerem danych wcf. Moja aplikacja jest zbudowana z głównych kategorii, podkategorii i produktów. Każdy produkt może być tylko w jednej podkategorii i moje URL to tak:Jak dodać nowy węzeł MvcSitemapProvider w środowisku wykonawczym

/maincategoryname/subcategoryname/{ProductId}/producttitle

a odpowiadający ślad nawigacyjny:

główna> Maincategory> Podkategoria> Producttitle

Używam obecnie MvcSitemapProvider do generowania menu nawigacyjnego i bułek tartych. Ładuję wszystkie adresy URL jako dynamiczne węzły bez pamięci podręcznej. To rozwiązanie działa dla kilku produktów, ale kiedy dodaję 1000 produktów, mapa witryny zajmuje 6,5 sekundy, co jest o wiele za długie.

Włączyłem buforowanie w MvcSitemapProvider. W ten sposób aplikacja ładuje się znacznie szybciej. Ale gdy użytkownik doda nowy produkt i przejdzie do nowego produktu (strony). Adres URL nie znajduje się jeszcze w pliku mapy witryny, ponieważ korzysta z pamięci podręcznej. W ten sposób moja nawigacja i bułka nie będą generowane.

Moje pytanie brzmi:

Czy jest możliwe aby dodać nowy węzeł do mapy przy starcie, gdy użytkownik dodaje nowy produkt?

Odpowiedz

0

MvcSiteMapProvider pozwala na Dynamic Sitemaps, który rozwiązuje dla Dependance cache.

Możesz to włączyć, tworząc klasę, która implementuje IDynamicNodeProvider. Poniżej znajduje się przykład, który generuje dynamiczne węzły na podstawie zapytania bazy danych, a także ustawia zależność pamięci podręcznej od tego samego zapytania.

public class ProductNodesProvider : IDynamicNodeProvider 
{ 
    static readonly string AllProductsQuery = 
    "SELECT Id, Title, Category FROM dbo.Product;"; 
    string connectionString = 
     ConfigurationManager.ConnectionStrings ["db"].ConnectionString; 

    /// Create DynamicNode's out of all Products in our database 
    public System.Collections.Generic.IEnumerable<DynamicNode> GetDynamicNodeCollection() 
    { 
    var returnValue = new List<DynamicNode>(); 

    using (SqlConnection connection = new SqlConnection(connectionString)) { 
     SqlCommand command = new SqlCommand (AllProductsQuery, connection); 
     connection.Open(); 
     SqlDataReader reader = command.ExecuteReader(); 
     try { 
     while (reader.Read()) { 
      DynamicNode node = new DynamicNode(); 
      node.Title = reader [1]; 
      node.ParentKey = "Category_" + reader [2]; 
      node.RouteValues.Add ("productid", reader [0]); 

      returnValue.Add (node); 
     } 
     } finally { 
     reader.Close(); 
     } 
    } 

    return returnValue; 
    } 

    /// Create CacheDependancy on SQL 
    public CacheDescription GetCacheDescription() 
    { 
    using (SqlConnection connection = new SqlConnection(connectionString)) { 
     SqlCommand command = new SqlCommand (AllProductsQuery, connection); 
     SqlCacheDependency dependancy = new SqlCacheDependency (command); 

     return new CacheDescription ("ProductNodesProvider") 
     { 
     Dependencies = dependancy 
     }; 
    } 
    } 
} 

Chociaż to wszystko jest bardzo ładne - i powinien unieważnić cache kiedy klienci zmienić produkty w datbase - cała SqlCacheDependancy może być trudne i jest SQL Server Version zależne.

Zamiast tego możesz użyć niestandardowego CacheDependacy, jeśli używasz pamięci podręcznej do przechowywania produktów.

5

Przyjęta odpowiedź jest teraz trochę nieaktualna. W MvcSiteMapProvider v4, nie istnieje już metoda GetCacheDescription() w DynamicNodeProvider. To i tak nie działało.

Można teraz invalidate the cache manually za pomocą [SiteMapCacheRelease] atrybut o metodach działania, które zaktualizować dane:

[MvcSiteMapProvider.Web.Mvc.Filters.SiteMapCacheRelease] 
[HttpPost] 
public ActionResult Edit(int id) 
{ 

    // Update the record 

    return View(); 
} 

Albo poprzez wywołanie statycznej metody:

MvcSiteMapProvider.SiteMaps.ReleaseSiteMap(); 

Masz również opcję teraz, aby rozszerzyć ramy do supply your own cache dependencies.

Powiązane problemy