+1-888-365-2779
Try Now
More in this section

Forums / Bugs & Issues / LINQ Projections Using DynamicContent Items Fail Using Execution Deferment

LINQ Projections Using DynamicContent Items Fail Using Execution Deferment

5 posts, 1 answered
  1. RJ Cuthbertson
    RJ Cuthbertson avatar
    41 posts
    Registered:
    01 Jun 2015
    27 Jul 2015
    Link to this post

    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:

    public class StationAmenityDetail
    {
        public StationAmenityDetail(DynamicContent dynamicContent)
        {
            DynamicContent relatedStation = dynamicContent.GetRelatedItems<DynamicContent>("Station").SingleOrDefault();
            if (relatedStation != null)
            {
                Station station = new Station(relatedStation);
                this.Code = station.Code;
            }
     
            this.Content = dynamicContent.GetValue<Lstring>("Content").Value;
        }
     
        public string Code { get; set; }
     
        public string Content { get; set; }
    }
     

    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:

    public static List<StationAmenityDetail> GetStationAmenityDetails(Guid stationAmenityId)
    {
        using (DynamicModuleManager dynamicModuleManager = DynamicModuleManager.GetManager(SitefinityContentUtility.StationAmenityDetailsProvider))
        {
            List<StationAmenityDetail> stationAmenityDetails = new List<StationAmenityDetail>();
     
            IQueryable<DynamicContent> details = dynamicModuleManager.GetDynamicDataItems(SitefinityContentUtility.StationAmenityDetailsType)
                .Where(sad => sad.SystemParentId == stationAmenityId);
     
            foreach (DynamicContent detail in details)
            {
                stationAmenityDetails.Add(new StationAmenityDetail(detail));
            }
     
            return stationAmenityDetails;
        }
    }

     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:

    public static List<StationAmenityDetail> GetStationAmenityDetails(Guid stationAmenityId)
            {
                using (DynamicModuleManager dynamicModuleManager = DynamicModuleManager.GetManager(SitefinityContentUtility.StationAmenityDetailsProvider))
                {
                    return dynamicModuleManager.GetDynamicDataItems(SitefinityContentUtility.StationAmenityDetailsType)
                        .Where(sad => sad.SystemParentId == stationAmenityId)
                        .AsEnumerable()
                        .Select(sad => new StationAmenityDetail(sad))
                        .ToList();
                }
            }

     

    However, when calling this on an IQueryable<DynamicContent> source, you get no related data back:

    public static List<StationAmenityDetail> GetStationAmenityDetails(Guid stationAmenityId)
    {
        using (DynamicModuleManager dynamicModuleManager = DynamicModuleManager.GetManager(SitefinityContentUtility.StationAmenityDetailsProvider))
        {
            return dynamicModuleManager.GetDynamicDataItems(SitefinityContentUtility.StationAmenityDetailsType)
                .Where(sad => sad.SystemParentId == stationAmenityId)
                .Select(sad => new StationAmenityDetail(sad))
                .ToList();
        }
    }

    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.

     

    Edit:

    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.

  2. RJ Cuthbertson
    RJ Cuthbertson avatar
    41 posts
    Registered:
    01 Jun 2015
    29 Jul 2015
    Link to this post

    Addition information:

    Moving the GetRelatedItems call to be a direct part of the LINQ expression causes an exception to occur. See the attached image.

  3. Nikola Zagorchev
    Nikola Zagorchev avatar
    424 posts
    Registered:
    24 Nov 2016
    30 Jul 2015
    Link to this post
    Hi Richard,

    We have addressed this in the support ticket you have opened for the issue. Please, feel free to update the thread and the community once we resolve the issue in the support case.

    Thank you for your cooperation and extended information provided.

    Regards,
    Nikola Zagorchev
    Telerik
     
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
     
  4. RJ Cuthbertson
    RJ Cuthbertson avatar
    41 posts
    Registered:
    01 Jun 2015
    05 Aug 2015
    Link to this post

    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 returned."

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

     

    Answered
  5. Nikola Zagorchev
    Nikola Zagorchev avatar
    424 posts
    Registered:
    24 Nov 2016
    05 Aug 2015
    Link to this post
    Hello RJ ,

    Thank you for sharing the information with the community.

    Regards,
    Nikola Zagorchev
    Telerik
     
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
     
5 posts, 1 answered