When pulling data from a dynamic module with a related dynamic content item, I've found some strange behavior. I have a model class defined as such:
DynamicContent relatedStation = dynamicContent.GetRelatedItems<DynamicContent>(
Station station =
.Code = station.Code;
.Content = dynamicContent.GetValue<Lstring>(
The constructor of the model encapsulates the data lookup logic here, with "Station" being the key of the related item.
If iterating the collection in a for each loop, this works as expected:
List<StationAmenityDetail> GetStationAmenityDetails(Guid stationAmenityId)
(DynamicModuleManager dynamicModuleManager = DynamicModuleManager.GetManager(SitefinityContentUtility.StationAmenityDetailsProvider))
List<StationAmenityDetail> stationAmenityDetails =
IQueryable<DynamicContent> details = dynamicModuleManager.GetDynamicDataItems(SitefinityContentUtility.StationAmenityDetailsType)
.Where(sad => sad.SystemParentId == stationAmenityId);
See "RelatedStationForEach.png" for a screenshot of the debugger showing that this works.
You get the same results if you use an in-memory LINQ projection against an IEnumerable<DynamicContent> source:
.Where(sad => sad.SystemParentId == stationAmenityId)
However, when calling this on an IQueryable<DynamicContent> source, you get no related data back:
See "RelatedStationIQueryable.png" for the debugger screenshot showing the related item comes back null.
I'm not sure if this is an issue with OpenAccess or with Sitefinity's DynamicContent class implementation, so if there is a different place to better report this, please let me know.
The correct behavior here (I believe) would be to throw a NotSupportedException like LINQ to Entities does (see Avoiding NotSupportedException with IQueryable).
The thing I really don't understand though is that the DynamicContent item passed to the model's constructor is populated in all of the above instances, meaning that the initial query to retrieve the "parent" item has already been executed by this point, however it fails to return related data as if it's missing some information about the context or the dynamic module manager. Instead of throwing an exception for not being able to execute the second set of queries, it just returns null and fails silently.
So a potential alternative behavior, I suppose, if you would like to retain the ability to use constructors with parameters in projections, would be to throw an exception when another query is being attempted if the necessary contextual information is not present to allow it to successfully perform the query.
Moving the GetRelatedItems call to be a direct part of the LINQ expression causes an exception to occur. See the attached image.
To summarize the conversation from the support ticket:
"This is partially a known issue. There is a case when performing LINQ over a IQueryable collection to
select an item, where the related items query will always return null,
since the items providers will not be queried. Since in Sitefinity DynamicContent implementation we do not store the
Provider name in the database, if it belongs to the default provider, we
get it from the Provider (Provider.Name). The Provider itself is a
complex object, i.e. it's not persisted in the database but is built
when you load the query from the database. Thus since the Provider is
still null when you work with the IQueryable item from the collection,
we are not able to get the provider name and thus no related data is
"There are several cases when getting the related data using the related data API will fail silently. One is the case, which you have found out. The others are if you execute the method over a collection - it is possible since its an extension method of object and if you specify wrong field name for the related data field."
"I was able to communicate the different behavior when using Related data in LINQ statements with the development. We will not be able to modify the current method behavior or throw an exception at that phase. However, we are working on extending the documentation for the Related Data API and note this cases, so this behavior is documented and clients are familiar with the behavior, so they can adjust their code."