Document api vs nodeFactory
Rating: 4,5 / 5 stars - 10 vote(s).
Lately, I’ve been involved in a few umbraco projects - also while answering questions on the forum – I find far too many times find people who are not completely aware of the difference between the document api and the use of the nodeFactory class that lives in the presentation namespace. So how do we know when to use the document api and when to use the nodeFactory.
In short, whenever there’s a need on the frontend to display any umbraco data, use the nodeFactory. Why? Because the nodeFactory provides fast read-only access to the umbraco data. Fast, as it gets its data from the umbraco xml cache, read-only as you’re not allowed – in fact, you just can’t – create or update umbraco data.
Last thing is the most important difference between the two methods. If you don’t need to update or create umbraco, use the nodeFactory. In all other cases, you’re free to use the document api.
Let’s build an example to show what’s going… Consider the following code examples:
1: var node = umbraco.presentation.nodeFactory.Node.GetCurrent();
2: var childNodes = node.Children;
3:
4: foreach (Node childNode in childNodes) {
5: foreach (Property property in childNode.Properties) {
6: Response.Write(property.Alias + "-" + property.Value);
7: }
8: }
and
1: var document = new Document(umbraco.presentation.nodeFactory.Node.GetCurrent().Id);
2: var subDocuments = document.Children;
3:
4: foreach (Document subDocument in subDocuments) {
5: foreach (Property property in subDocument.getProperties) {
6: Response.Write(property.PropertyType.Alias + "-" + property.Value);
7: }
8: }
Basically, both examples will take the current page being browsed and output a list of properties and their values for each of the child pages. First code sample is using the optimized method while the latter uses the document api. In order to actually find out why the first method is superior to the second, we need to add these code samples to a public page in umbraco. I’ve done so by creating some user controls, corresponding macro’s and put those macro’s onto a template. Next to that, you should also fire up the Sql Profiler that comes with the Sql Server Management Studio in order to find out whether the database is being queried and how often.
I really encourage to run this test on a local install. I’ve done the same on a local umbraco installation of mine, threw the macro’s onto a page template which had 2 child pages. Each of those pages has two properties. Here’s the outcome from the Sql Profiler when using the document api (2nd code sample). Of course, node id’s may be different on your install.
1: SELECT createDate, trashed, parentId, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text FROM umbracoNode WHERE id = 1050
2: Select versionId from cmsContentVersion where contentID = 1050 order by id desc
3: select Count(published) as tmp from cmsDocument where published = 1 And nodeId =1050
4: SELECT createDate, trashed, parentId, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text FROM umbracoNode WHERE id = 1071
5: SELECT createDate, trashed, parentId, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text FROM umbracoNode WHERE id = 1080
6: SELECT createDate, trashed, parentId, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text FROM umbracoNode WHERE id = 1071
7: Select versionId from cmsContentVersion where contentID = 1071 order by id desc
8: select Count(published) as tmp from cmsDocument where published = 1 And nodeId =1071
9: SELECT createDate, trashed, parentId, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text FROM umbracoNode WHERE id = 1080
10: Select versionId from cmsContentVersion where contentID = 1080 order by id desc
11: select Count(published) as tmp from cmsDocument where published = 1 And nodeId =1080
12: SELECT createDate, trashed, parentId, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text FROM umbracoNode WHERE id = 1045
13: Select masterContentType,Alias,icon,thumbnail,description from cmsContentType where nodeid=1045
14: SELECT dataNvarchar FROM cmsPropertyData WHERE id = 98
15: SELECT createDate, trashed, parentId, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text FROM umbracoNode WHERE id = -49
16: select dbType, controlId from cmsDataType where nodeId = '-49'
17: SELECT DataInt FROM cmsPropertyData WHERE id = 99
18: SELECT createDate, trashed, parentId, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text FROM umbracoNode WHERE id = 1045
19: Select masterContentType,Alias,icon,thumbnail,description from cmsContentType where nodeid=1045
20: SELECT dataNvarchar FROM cmsPropertyData WHERE id = 100
21: SELECT DataInt FROM cmsPropertyData WHERE id = 101
A total of 21 database queries to ouput 2 properties of two child pages. A lot of queries, whereas the first method using the nodeFactory WON’T HIT THE DATABASE at all. Also, be aware that using the document api, you will also be listing the NON-PUBLISHED pages, as there’s no check whether the document is published in the second code sample (.Published property), which would mean ever more database queries to do the lookup.
Conclusion: Always use the nodeFactory when there’s only a need for displaying data. Go check your code and start optimizing!