In the Umbraco back office, I create a new node, set the dropdown to one of the values above and publish the node. The umbraco.config disk cache is then updated with something like this:
It contains the text part of the pre value, not the Id.
In my code I then do this:
var content = ContentService.GetById(1234);
content.Properties["googleXMLSitemapChangeFrequency"].Value;
Which returns 68, not the value "weekly" as stored in the disk cache.
This raises 2 questions:
1. What is the correct way using the V6 API to get the text value - should I still be using:
umbraco.library.GetPreValueAsString(68)
I always cringe when I have to use umbraco.library as it feels like legacy code from the dark days of XSLT macros.
2. This is probably more pertinent. Why doesn't the ContentService use the disk cache, or any cache for that matter. I've run a SQL profiler and every request I make to the ContentService results in SQL queries being generated and executed against the DB. For high volume site this is going to be a major issue.
First thing to note is that the Properties on an IContent object will always contain the raw values, which correspond to what is saved in the database. With regards to rendering, the values might be formatted in some other way using some kind of IPropertyEditorValueConverter.
In order to get the Prevalues you need to use the DataType service and the Id of the DataTypeDefinition that the 'googleXMLSitemapChangeFrequency' PropertyType is referencing. So when you have your content-object you would do something like this:
var cs = ServiceContext.ContentService; var ds = ServiceContext.DataTypeService;
This will return a list with all prevalues defined for that DataType. We currently don't have a method that corresponds to the library.GetPreValueAsString method, but we probably should have.
As for your second question the ContentService does use caching under the hood, which for IContent is a runtime cache that expires after 5 minutes. So when the same content is loaded again and again it shouldn't infer multiple hits to the database. Any kinds of queries like GetChildren or GetByLevel will of course run against the database, but any items found in those types of queries will be retrieved from cache before going to the database. But please note that the backoffice is still using a lot of legacy code, which will make a lot of db calls.
Your example makes perfect sense and my confusion was probably based in "thinking in an Umbraco 4.X way" where everything was read from the XML Store.
I can easily write an abstraction around the DataTypeService that gives me something similar in functionality to umbraco.library.GetPreValueAsString() until there is a helper for this added to the core libs. I might even look at creating (and submitting) a patch for Umbraco.Core that does this.
Also, it's nice to know that there is some caching going on - I'll need to look at this in more detail in my implementation because it still seems to me like there is a lot of DB chatter everytime I make a (front end) page request but this is likely to be something I'm doing wrong in my code!
If the DB hits you are seeing is from the front end then it might be related to looking up Template information or if you are using the dynamic stuff that was introduced in v4. But either way it would be good to learn more about this, and I'm always interested in hearing what you might find.
Just chiming in here with a quick unrelated question to the OP
It sounds like ContentService and the like talk directly to the database, yes? Is recommended to still use ContentService on the front-end, instead of NodeFactory which reads from the XML cache? (For example, in a usercontrol). Or is ContentService only meant for "backend" usage ie the Document API?
hi Morten - what was the method that was added? I'm using 7.2 can wish to get the prevalue text for the values selected on my IContent, not all of the prevalues on the datatype definition. thanks
I just wrote my own extension to get the text of the prevalues of a certain property on my IContent item, but wondering if there is an extension in the core now that I should use instead? thanks
public static string GetPrevalues(this IContent content, IDataTypeService ds, string alias)
{
var ids = content.GetValue<string>(alias).Split(',').ToList();
var list = ids.Select(x => ds.GetPreValueAsString(int.Parse(x)));
return string.Join(",", list);
}
V6 IContent and PreValue Properties
Hi,
I've built a site which is currently using Umbraco 6.0.2
I'm using the ContentService to retrieve instances of IContent as per Niels blog post here: http://umbraco.com/follow-us/blog-archive/2013/1/22/introducing-contentservice-aka-the-v6-api.aspx
One of my DocTypes has a Dropdown list data type that has the following pre values:
In the Umbraco back office, I create a new node, set the dropdown to one of the values above and publish the node. The umbraco.config disk cache is then updated with something like this:
It contains the text part of the pre value, not the Id.
In my code I then do this:
var content = ContentService.GetById(1234); content.Properties["googleXMLSitemapChangeFrequency"].Value;
Which returns 68, not the value "weekly" as stored in the disk cache.
This raises 2 questions:
1. What is the correct way using the V6 API to get the text value - should I still be using:
I always cringe when I have to use umbraco.library as it feels like legacy code from the dark days of XSLT macros.
2. This is probably more pertinent. Why doesn't the ContentService use the disk cache, or any cache for that matter. I've run a SQL profiler and every request I make to the ContentService results in SQL queries being generated and executed against the DB. For high volume site this is going to be a major issue.
Hi Jon,
First thing to note is that the Properties on an IContent object will always contain the raw values, which correspond to what is saved in the database. With regards to rendering, the values might be formatted in some other way using some kind of IPropertyEditorValueConverter.
In order to get the Prevalues you need to use the DataType service and the Id of the DataTypeDefinition that the 'googleXMLSitemapChangeFrequency' PropertyType is referencing. So when you have your content-object you would do something like this:
This will return a list with all prevalues defined for that DataType. We currently don't have a method that corresponds to the library.GetPreValueAsString method, but we probably should have.
As for your second question the ContentService does use caching under the hood, which for IContent is a runtime cache that expires after 5 minutes. So when the same content is loaded again and again it shouldn't infer multiple hits to the database. Any kinds of queries like GetChildren or GetByLevel will of course run against the database, but any items found in those types of queries will be retrieved from cache before going to the database. But please note that the backoffice is still using a lot of legacy code, which will make a lot of db calls.
Hope this answers your questions
- Morten
Hi Morten,
Thanks for taking the time to respond.
Your example makes perfect sense and my confusion was probably based in "thinking in an Umbraco 4.X way" where everything was read from the XML Store.
I can easily write an abstraction around the DataTypeService that gives me something similar in functionality to umbraco.library.GetPreValueAsString() until there is a helper for this added to the core libs. I might even look at creating (and submitting) a patch for Umbraco.Core that does this.
Also, it's nice to know that there is some caching going on - I'll need to look at this in more detail in my implementation because it still seems to me like there is a lot of DB chatter everytime I make a (front end) page request but this is likely to be something I'm doing wrong in my code!
High Five, sir, You Rock!
;-)
If the DB hits you are seeing is from the front end then it might be related to looking up Template information or if you are using the dynamic stuff that was introduced in v4. But either way it would be good to learn more about this, and I'm always interested in hearing what you might find.
- Morten
Just a quick update: I have added the method in question to 6.0.3, so once that is released the method will be available to use.
- Morten
Just chiming in here with a quick unrelated question to the OP
It sounds like ContentService and the like talk directly to the database, yes? Is recommended to still use ContentService on the front-end, instead of NodeFactory which reads from the XML cache? (For example, in a usercontrol). Or is ContentService only meant for "backend" usage ie the Document API?
hi Morten - what was the method that was added? I'm using 7.2 can wish to get the prevalue text for the values selected on my IContent, not all of the prevalues on the datatype definition. thanks
I just wrote my own extension to get the text of the prevalues of a certain property on my IContent item, but wondering if there is an extension in the core now that I should use instead? thanks
is working on a reply...