On IManager GetItem/GetItemOrDefault throw exception when item does not exist.
This is an error related to the solution on this page: http://www.sitefinity.com/developer-network/forums/developing-with-sitefinity-/get-tags-from-pagecontrols
I have an implementation of IManager. In this case I get it by calling DynamicModuleManager.GetManager(). If I call GetItem and the item has been deleted then it throws the following error:
I found this odd as I would expect a function that retrieves an item to return NULL if it could not find it, or at least a relevant error. Then I ran across GetItemOrDefault and figured that it would return the default for the type (NULL) if it couldn't find it. Instead it throws a different error:
I found the error rather confusing since the data item type is identical to the supposed accepted item type. So my question is: How can I figure out if an item exists before I call GetItem on an implementation of IManager?
Just freehand, here's my method - let's use pages as an example:
And if it's content, usually make sure it's published:
Thanks for the suggestion. Do you know if the SingleOrDefault uses Linq-to-Entities/SQL or Linq-to-Objects? I wouldn't want to be returning all images or all pages from a sql statement and then sifting through the responses in memory rather than getting just the record I want as the result of a sql statement. Since the "GetItems" call off of the IManager interface returns an IEnumerable rather than an IQueryable I suspect that SingleOrDefault is using Linq-to-Objects at that point (ref: msdn.microsoft.com/.../bb397919.aspx). I wouldn't know how to setup EFTrace for Sitefinity to check. Do you know?
Based on that assumption, it seems that my best bet is to wrap my "GetItem" calls in a try/catch and return Default(T) on error.
No probs... I'm not a guru of this by any means, but I just ran a SQL trace using the 2nd snippet - GetImages() which seemed to execute two queries: (I've cut out the sp_prepexec stuff and replaced paramaterised variables with their values:
This returns "19" for my test database... Suggesting 19 images in my database I think. Suspect if the above query returns zero, then you get a null return.
Next, seeing as the above was fine, it ran:
Note the TOP(2) clause, meaning the return from SQL is limited. Suggest then that if two were returned by the query that the code throws the "more than one object" exception.
I just used SQL server profiler, capturing data into a table so I could query it to gather this information - oh.. SF Version 5.3.3900, SQL 2008R2
Suggest that this sounds less expensive than catching an exception, though I don't know for sure.. It feels more "clean" anyway.
Thanks for the information. I am surprised that it works that way. I find it odd that it does a TOP(2). I would have expected a TOP(1).
"SingleOrDefault" will throw an exception if >1 return. If the SQL query was limited to 1 result only, C# would have no way of knowing if >1 was returned - hence the TOP(2)
Ah, makes sense.