On IManager GetItem/GetItemOrDefault throw exception when it

Posted by Community Admin on 04-Aug-2018 22:03

On IManager GetItem/GetItemOrDefault throw exception when item does not exist.

All Replies

Posted by Community Admin on 08-Feb-2013 00:00

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:

[NullReferenceException: Object reference not set to an instance of an object.]
DynamicModule.ns.Wrapped_OpenAccessDynamicModuleProvider_8757eda9740b460eab5ca64f3e106cb1.GetItem(Type itemType, Guid id) +322
Telerik.Sitefinity.Data.ManagerBase`1.GetItem(Type itemType, Guid id) +96

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:

[ArgumentException: Invalid data item type "Telerik.Sitefinity.DynamicModules.Model.DynamicContent". Accepted item types are: "Telerik.Sitefinity.DynamicModules.Model.DynamicContent".]
DynamicModule.ns.Wrapped_OpenAccessDynamicModuleProvider_70eb871433ea455abe06db6a5ded8ba2.GetItemOrDefault(Type itemType, Guid id) +322
Telerik.Sitefinity.Data.ManagerBase`1.GetItemOrDefault(Type itemType, Guid id) +96

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?


Posted by Community Admin on 09-Feb-2013 00:00

Just freehand, here's my method - let's use pages as an example:

var item = PageManager.GetManager().GetPageNodes().SingleOrDefault(o => o.Id == MyGuid);

And if it's content,  usually make sure it's published:

var image = LibrariesManager().GetManager().GetImages().SingleOrDefault(o => o.Id == MyGuid && o.Visible && o.Status = ContentLifecycleStatus.Live);

Posted by Community Admin on 11-Feb-2013 00:00

Hi Stephen,

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.

Posted by Community Admin on 11-Feb-2013 00:00

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:

SELECT COUNT(1) FROM ( SELECT a.[content_id] AS COL1, a.[voa_class] AS COL2, ... AS COL40 FROM [sf_libraries] a WHERE a.[app_name] = '/Libraries') AS TMP_COUNT

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:

SELECT  TOP(2) a.[content_id] AS COL1, a.[voa_class] AS COL2, ... AS COL49
FROM [sf_media_content] a
WHERE a.[app_name] = '/Libraries'
AND a.[content_id] = '74DB6EA1-70A8-4A5D-904B-2FE64791F985'
AND a.[visible] <> 0
AND a.[status] = 2
AND a.[voa_class] = 1053642113

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.

Posted by Community Admin on 11-Feb-2013 00:00

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).

Posted by Community Admin on 11-Feb-2013 00:00

"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)


Posted by Community Admin on 11-Feb-2013 00:00

Ah, makes sense.

This thread is closed