Developer forum

Forum » Feature requests » ItemService - GetItems.

ItemService - GetItems.

Claus Kølbæk
Claus Kølbæk
Reply

Hey

So I was upgrading a solution to 9.3.5 and noticed that ItemManager.Storage.GetByParentPageId was noted as obsolete - but the closest replacement I could find was GetItemByPageId in 9.4 - so not any real replacement smiley - Do you plan on replacing, or is there another smart way to get the same result? (Soo half a question and if no real answer - then a feature request).


Replies

 
Nicolai Pedersen
Reply
This post has been marked as an answer

Since this is page related, you should use the pageservice instead - you should get that as a hint from the obsulete statement. So use PageService.GetPagesByParentID and take their .Item property to get access to those.

BR Nicolai

Votes for this answer: 1
 
Claus Kølbæk
Claus Kølbæk
Reply

Thanks for the response - The hint makes more sense to me today than it did friday :)

While we are on the topic of the new services - what is the idea behind the fact that paragraphService.GetParagraphsByPageId only returns active paragraphs while paragraphService.GetParagraph returns inactive aswell? Also - should there not be a .active state to check for on a paragraph, similar to Content.Page.Active ?

Also just a thing for consideration - something like this:  var servicePages = pageService.GetPagesByParentID(123).Where(x => x.Published); is usually what I want to achieve whenever I get pages, and while this works fine, it could maybe just be a parameter for get the GetPages like GetPagesByParentID(servicePageId, Active) or GetPagesByParentID(servicePageId, Published)?.

 
Nicolai Pedersen
Reply

Hi Claus

In the source code GetParagraphsByPageId and GetParagraph both return from the same internal index of all paragraphs - all paragraphs are loaded and indexed in the paragraph service cache and both methods return data from that (9.3+). So are you sure you only get active paragraphs?

The paragraph equivalent to Page.Active is Paragraph.ShowParagraph - sorry about the naming confusion. But paragraphs have 2 states - show or hide in frontend. Pages have more states based on Page.Active, Page.Hidden and Page.Published combinations.

Page.Active means the page is not viewable in the frontend at all. Page.Hidden means it is viewable, but not in navigations. Page.Published is based on a combination of publication periods and hidden feature.

So that would require a number of overloads on the pageservice to cover all scenarios - using the Linq approach puts you in charge. I'll add a backlog to include overloads on some methods covering Active and Published. Maybe an enum of PublishState.All (All pages), PublishState.Active (All active pages) and PublishState.Published (All active, not hidden pages in publication period). Let me hear your thoughts.

BR Nicolai

 
Claus Kølbæk
Claus Kølbæk
Reply

I thought my extensive 1 test had confimed it was only active paragraphs but no, you are ofc. right in that it takes them all :)

And ye thanks for the ShowParagraph - I must have scrolled by it a few times.

I am a big fan of the new services especially the easy sorting and filtering allowed by Linq on top of it, and I can also see that if you add such an enum, then someone will be wondering why fx Page.Hidden is not an option. So personally I would like enum solution you suggested, or maybe it would make sense to pass a PublishState object that could handle more / all options instead.

 
Martin Vang
Martin Vang
Reply

Sorry about jumping into this (very exciting) discussion near the end. I have a question. :)

The PageService (and really all our new services) give a very special promise for methods they expose: "If you use me, I will take care of everything to make the performance good".

So the discussion above: Considering that you're adding a filter for the returned data, I will have to make something to iterate all the returned data: This performs significantly worse, then the other methods of the service...

So given that you want convenience of use (which is important!), I would like to discuss how we can best make it easy to generate slow-performing filters for the fast-performing services.

  • Is it enough to mark the methods that are "slow" with a keyword or similar in the doc?
  • Should these filters be handled by something else than the service itself?
  • Some even smarter idea?

To sum it up: How should we inform about if a method is meant for convenience BUT is inefficient?

If doing the math, I would say that using a filter on the returned data is about twice as slow as not having the filter. And while that might not be a problem for our PageService, it will be a problem when we implement the same for ProductService (comming in 9.4).

BR

Martin

 
Claus Kølbæk
Claus Kølbæk
Reply

And UserService in 9.4.1? :)

Happy to have you join in Martin!
I think you more often than not, would want to filter the data - when you use get pages by parent id - you have already supplied a filter, which I would think is similar in performance hit as simply sorting it with link or a foreach with an if statement. - The cases where you would ever just want all pages, paragraphs or products as you say, seems very limited too me.
So if you say it is meant for convenience but is inefficient, and you want to warn about that - then that warning would instantly make me wonder what the more effecient solution would be? 

Let say you use the productService but would only want the currently published products - would there be a difference in performance hit between foreach, linq and parameter as options? - because if not, then I don't really see the need for a warning :)

 
Martin Vang
Martin Vang
Reply

Hi Claus,

Alright, I guess I have to use a bit of slightly simplified math to show the issue. I know this stuff is a bit difficult, but I don't see how to explain it without a bit of notation.

var servicePages = pageService.GetPagesByParentID(123)

The above operation looks in a dictionary to find the parent with id 123: O(1).

Then it looks at where this parent is in the tree: O(1).

Then it returns all children at this position in the tree: O(#children) = O(n) <--- Can be improved to (1)

Then it sorts by id: O(n) <--- Can be improved to O(1)

Total: O(2n) <--- Can be improved to O(1)

.Where(x => x.Published)

The method above loops through all elements: O(n) <--- Cannot be improved!

Each element accesses Published (a simple boolean property): O(1)

Total: O(n)

This means, that roughly speaking, you spend between 50% and n orders more time (if we spend time to improve performance of this method in the future) to filter out all the pages that are not published, then you do just returning all the pages.

If we end up not supporting the typical use-case, we ofc. need to change the datastructure to support it, such that what you typically do is fast.

 

Foreach, linq and parameters are all going to do exactly the same, so there is no significantly difference (actual runtime by vary alot, but this will change depending upon the version of the JIT compiler).

BR

Martin

 
Claus Kølbæk
Claus Kølbæk
Reply

Hej Martin

Finally found some minuts to read through it all :)

If I understand you correctly, you are saying that in some cases you are able to optimize the performance of retrieving specific pages, better than we ourselves can do by getting out all and sorting through them - though it would be on a case by case scenario, correct? I understand that simply getting all would be fastest but it is really rare that, that is what you want.
Which is why as I see it, the best solution is still to make the methods for specific scenarios such as get pages by parent page etc. and then you can optimize on the method over time - I get that as Nicolai mentions, it would require a high number of overload to cover all the bases, which is fine, as you can easily just add them over time aswell - I would prob. consider having a sort object to pass along or something - as it could then be the exact same thing for pages, users products etc. (get parent node for node id etc.) instead of having to remember the inifite ways you can think of naming them :)

 
Imar Spaanjaars Dynamicweb Employee
Imar Spaanjaars
Reply

I just ran into the exact same thing (http://doc.dynamicweb.com/forum/dynamicweb-9-0-upgrade-issues/using-itemmanager-storage-getbyparentpageid?PID=1605) Would it make sense to provide a little more context on this (and similar) Obsolete attribute(s)? If it had said "Use a PageService to retrieve the parent pages and then accesss their Item property" I would have been able to figure it out without posting here.

Thanks!

Imar