Anders Hattestad
Jun 14, 2012
visibility 6569
star star star star star
(3 votes)

Find pages a lot faster without using FindPagesWithCriteria

I have in some projects had the need to get different pages from all over my site with some criteria’s. This could have been a job for FindPagesWithCriteria, but I was a bit concerned about the performance. I therefore made myself a Dynamic DataStore table that have those page data properties I want to query against with queries like this

  1. var q = from item in Items where
  2.             item.BoolProperties.Contains("PageVisibleInMenu")
  3.         orderby item.StartPublish
  4.         select item;

Every time a page is published, moved or deleted I update the store. If the page is the master language I also update the other languages. This was actually the tricky part. With replacement languages on like this

image

The page.PageLanguages only returns the languages the page have values on. Therefore one have to get all those language pages like this:

  1. PageDataCollection languageBranches = DataFactory.Instance.GetLanguageBranches(page.PageLink);
  2. foreach (LanguageBranch current2 in LanguageBranch.ListEnabled())
  3. {
  4.     if (current2.LanguageID.ToUpper() != page.MasterLanguageBranch.ToUpper())
  5.     {
  6.         PageLanguageSetting pageLanguageSetting2 = PageLanguageSettingsTree.Instance.Get(page.PageLink, current2.LanguageID);
  7.         bool flag = languageBranches.Exists(page.PageLink, current2.LanguageID);
  8.         if (flag || (pageLanguageSetting2 != null && pageLanguageSetting2.IsActive))
  9.         {
  10.  
  11.             var page3 = EPiServer.DataFactory.Instance.GetPage(page.PageLink, LanguageSelector.Fallback(current2.LanguageID, true));
  12.             if (page3 != null)
  13.             {
  14.                 if (page3.IsDeleted)
  15.                     DeletePage(page3.PageLink, current2.LanguageID);
  16.                 else
  17.                     UpdatePage(page3, current2.LanguageID);
  18.             }
  19.  
  20.         }
  21.     }
  22. }

The actually DDS table have some known properties, and one can add other here as needed. I’m using a concept with bool properties, and for every property that is true I added to the text string BoolProperties. This includes the dynamic properties as well.

  1. [EPiServerDataStore(AutomaticallyRemapStore = true, AutomaticallyCreateStore = true)]
  2. public class EPiServerPageInfo : DDS_BaseData<EPiServerPageInfo>
  3. {
  4.     public string PageName { get; set; }
  5.  
  6.     [EPiServerDataIndex]
  7.     public string PageReferenceString { get; set; }
  8.     [EPiServerDataIndex]
  9.     public string LanguageID { get; set; }
  10.     [EPiServerDataIndex]
  11.     public bool IsMasterLanguageBranch { get; set; }
  12.     public string MyCurrentPath { get; set; }
  13.     [EPiServerDataIndex]
  14.     public DateTime StartPublish { get; set; }
  15.     [EPiServerDataIndex]
  16.     public DateTime StopPublish { get; set; }
  17.     [EPiServerDataIndex]
  18.     public DateTime Changed { get; set; }
  19.     [EPiServerDataIndex]
  20.     public int PageTypeID { get; set; }
  21.     public string BoolProperties { get; set; }

With have values like this:

image

When I publish/delete or move a page I hookup on the events like this

  1. public class AttachEvents : PlugInAttribute
  2. {
  3.     public static void Start()
  4.     {
  5.         EPiServer.DataFactory.Instance.PublishedPage += new EPiServer.PageEventHandler(Instance_PublishedPage);
  6.         EPiServer.DataFactory.Instance.MovedPage += new EPiServer.PageEventHandler(Instance_MovedPage);
  7.         EPiServer.DataFactory.Instance.DeletedPage += new EPiServer.PageEventHandler(Instance_DeletedPage);
  8.     }
  9.  
  10.     static void Instance_DeletedPage(object sender, EPiServer.PageEventArgs e)
  11.     {
  12.         EPiServerPageInfo.EnsurePage(e.Page);
  13.     }
  14.     static void Instance_PublishedPage(object sender, EPiServer.PageEventArgs e)
  15.     {
  16.         EPiServerPageInfo.EnsurePage(e.Page);
  17.     }
  18.     static void Instance_MovedPage(object sender, EPiServer.PageEventArgs e)
  19.     {
  20.         EPiServerPageInfo.EnsurePage(e.Page);
  21.         if (e.TargetLink.CompareToIgnoreWorkID(PageReference.WasteBasket) || e.PageLink.CompareToIgnoreWorkID(PageReference.WasteBasket))
  22.         {
  23.             DoChildren(e.PageLink);
  24.         }
  25.     }
  26.     static void DoChildren(PageReference start)
  27.     {
  28.         foreach (var child in EPiServer.DataFactory.Instance.GetChildren(start,LanguageSelector.MasterLanguage()))
  29.         {
  30.             EPiServerPageInfo.EnsurePage(child);
  31.             DoChildren(child.PageLink);
  32.         }
  33.     }
  34. }

and update this store with the new values

  1. public static void UpdatePage(PageData page, EPiServerPageInfo row)
  2. {
  3.     row.PageName = page.PageName;
  4.     row.IsMasterLanguageBranch = page.IsMasterLanguageBranch;
  5.     row.StartPublish = page.StartPublish;
  6.     row.StopPublish = page.StopPublish;
  7.     if (page.Changed > row.Changed)
  8.         row.Changed = page.Changed;
  9.     row.PageTypeID = page.PageTypeID;
  10.     var boolItems=FindBoolProperties(page);
  11.     var b = "";
  12.     foreach (var key in boolItems.Keys)
  13.         b += " " + key + " ";
  14.     row.BoolProperties = b;
  15.     row.MyCurrentPath = DigFather(page);
  16. }

If one has special elements one would like to query against its only to add that property to the DDS class and to update the UpdatePage method.

The code is here

Jun 14, 2012

Comments

Anders Hattestad
Anders Hattestad Jun 15, 2012 09:01 AM

If one would like to update the DDS table when a dynamic property is called there is a partial solution here
http://world.episerver.com/Blogs/Anders-Hattestad/Dates/2011/2/Know-your-enemy-Sun-Tzus-The-Art-of-War/

Jun 18, 2012 02:08 PM

How much faster is this approach compared to FindPagesWithCriteria?

Anders Hattestad
Anders Hattestad Jun 18, 2012 02:53 PM

Dont have any numbers, but if you only want the 5 latest pages this method will provide that possibility. FindPagesWithCriteria will have to return all the pages...

error Please login to comment.
Latest blogs
Implementing the Bynder DAM Connector with Optimizely SaaS CMS: Lessons Learned

What I learned while integrating Bynder DAM with Optimizely SaaS CMS, exploring Optimizely Graph, and building a headless frontend experience....

Vipin Banka | Jul 3, 2026

Optimizely London developer meetup 2026: a round up

Well, what can I say? Last night we wrapped up! Yet another London Developer Meetup, hosted at the superb Lightwell venue And this is also a...

Scott Reed | Jul 3, 2026

AvantiBit Custom Settings for Optimizely CMS

AvantiBit Custom Settings is a free, Apache-2.0 Optimizely CMS add-on for typed, site- and language-aware configuration that stays out of content...

Enes Bajramovic | Jul 3, 2026 |

Building an experience with Visual Builder in Optimizely CMS 13

Visual Builder changes how we can think about campaign pages, landing pages and other highly curated editorial experiences in Optimizely CMS. Inste...

Pär Wissmark | Jul 2, 2026 |

LanguageMaster! From Managing to Mastering Languages!

Two years ago, I released my first Optimizely add-on . It was an extension to the Labs.LanguageManager tool from Optimizely that allowed the user t...

Matt Pallatt | Jul 2, 2026

List Properties of a Optimizely Content Type programmatically

Properties are simply fields used to create a content type in Optimizely. Lets explore how to get a list of properties of a specific content type...

Akash Borkar | Jul 2, 2026