November Happy Hour will be moved to Thursday December 5th.

Does GetDescendents hit the cache?

Vote:
 

Does GetDescendents hit the cache before going to the DB? I've found a few articles/blog posts that claim it doesn't, but they're all pre-7.x, and I can't find anything more recent to debunk them.

If it does hit the cache, is there any performance or technical reason to use GetDescendents vs calling GetChildren recursively?

#87095
Jun 09, 2014 19:14
Vote:
 

Hi Joseph,

GetDescendents will also hit the cache.

On my machine, both GetDescendents and GetChildren take 52-56 ms (approx  2 000 pages).

GetChildren does have a slightly better "cold start".

Solution with GetChildren:

private readonly IContentRepository _contentRepository =
    ServiceLocator.Current.GetInstance<IContentRepository>();

private void GetChildrenRecursive(ContentReference parent, List<IContent> list)
{
    foreach (var child in _contentRepository.GetChildren<IContent>(parent))
    {
        list.Add(child);
        GetChildrenRecursive(child.ContentLink, list);
    }
}

public void Test()
{
    var list = new List<IContent>();

    var sw = Stopwatch.StartNew();
    GetChildrenRecursive(ContentReference.StartPage, list);
    var elapsedTime = sw.ElapsedMilliseconds;
}

Solution with GetDescendents:

public void Test()
{
    var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();

    var sw = Stopwatch.StartNew();
    var list = contentRepository.GetDescendents(ContentReference.StartPage)
                                .Select(contentRepository.Get<IContent>)
                                .ToList();
    var elapsedTime = sw.ElapsedMilliseconds;
}

GetDescendets returns only ContentReference(s) and cannot filter pages by type. If you don't need to filter descendants by type, I guess that GetDescendets is more readable than recursive function (or maybe not :) )

#87177
Edited, Jun 10, 2014 10:10
Vote:
 

The issue with GetDescendents and doing a GetPage for each can mean quite alot of work for you. Though the GetItems that takes an IEnumerable<ContentReference> method found on DataFactory through the might help you out a little to batch the contentloading up.

#87339
Jun 10, 2014 21:31
Vote:
 

Hi

If you use the right functions there should be a preformance gain by using

var allPages=EPiServer.DataFactory.Instance.GetItems(EPiServer.DataFactory.Instance.GetDescendents(PageReference.StartPage),LanguageSelector.MasterLanguage())
This will use methods
GetItems => LoadBatched => GetScatteredContents => LoadContents (from DefaultContentProvider) =>
this._contentListDBAccessor().LoadSpecificContentInstances(contentLinks, languageBranchID);
That function will load alll not previsue loaded items in one go from the database.

public IList<IContent> LoadSpecificContentInstances(int[] contentLinks, int languageBranchID)
{
return base.Database.Execute<IList<IContent>>(delegate
{
DbCommand dbCommand = this.CreateCommand("netPageListPaged");
byte[] array = new byte[4 * contentLinks.Length];
int num = 0;
int[] contentLinks2 = contentLinks;
for (int i = 0; i < contentLinks2.Length; i++)
{
int num2 = contentLinks2[i];
array[num++] = (byte)(num2 >> 24 & 255);
array[num++] = (byte)(num2 >> 16 & 255);
array[num++] = (byte)(num2 >> 8 & 255);
array[num++] = (byte)(num2 & 255);
}
dbCommand.Parameters.Add(this.CreateParameter("Binary", DbType.Binary, ParameterDirection.Input, array));
dbCommand.Parameters.Add(this.CreateParameter("Threshold", Settings.Instance.StringDelayedLoadThreshold));
dbCommand.Parameters.Add(this.CreateParameter("LanguageBranchID", DbType.Int32, ParameterDirection.Input, languageBranchID));
return this.ReadPageList(dbCommand);
});
}

#87654
Jun 18, 2014 18:06
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.