Nzall
Nzall

Reputation: 3565

double order by in Dynamics CRM 2011 Linq query

I'm developing a survey module for CRM 2011, where a CRM user can make a survey with multiple questions of different types and ask contacts to answer them using a dynamic web page on Azure. I have completed about 90% of it so far and just need to add a few minor changes involving data management.

The part I'm currently optimizing involves sorting my questions. I have 2 entities in CRM: surveyquestion and question. question refers to an actual question in the survey, while surveyquestion is an N-N relationship entity with a few additional fields, so we can reuse questions in different surveys. I have a field "groep" in "question" which is used to indicate whether a question should be grouped with another question on the form. I have another field, "volgorde" in "surveyquestion", which is used to indicate the order of the questions. I wish to show all questions with the same "group" together, and then order any questions inside groups (and ungrouped questions as a separate group) by the sortorder field. So I basically need to order on 2 fields in 2 different tables, which seems to be quite tricky.

This is the code I'm currently using. I'm getting a nullreferenceexception on the join for vraaglist, which is weird because both vr.Id and ev.slfn_vraag.Id have data in the relevant rows. I don't think it's due to the orderby, because the commented code above works (but I cannot simply add ev.volgorde to my orderby because he complains about that.

public List<slfn_vraag> GetVragenforEnquete(Guid enGuid)
    {
        //List<slfn_vraag> vraaglist = (from vr in _oContext.slfn_vraagSet
        //                              join ev in _oContext.slfn_enquetevraagSet on vr.Id equals ev.slfn_vraag.Id
        //                              orderby vr.slfn_Groep
        //                              where ev.slfn_enquete.Id == enGuid
        //                              select vr).ToList();

        IQueryable<slfn_enquetevraag> enquetevraaglist = (from ev in _oContext.slfn_enquetevraagSet
                                       orderby ev.slfn_volgorde
                                       where ev.slfn_enquete.Id == enGuid
                                       select ev);
        List<slfn_vraag> vraaglist = (from vr in _oContext.slfn_vraagSet
                                      join ev in enquetevraaglist on vr.Id equals ev.slfn_vraag.Id
                                      orderby vr.slfn_Groep
                                      select vr).ToList();
        return vraaglist;
    }

The code compiles without errors, but when i run it, I get a NullReferenceException on the question query. does anyone have any ideas on how to fix this?

edit: exception details from VS2012 as requested below.

  System.NullReferenceException occurred
  HResult=-2147467261
  Message=De objectverwijzing is niet op een exemplaar van een object ingesteld.
  Source=Microsoft.Xrm.Sdk
  StackTrace:
       bij Microsoft.Xrm.Sdk.Linq.QueryProvider.TranslateJoin(QueryExpression qe, IList`1 methods, Int32& i, Projection& projection, List`1& linkLookups)
       bij Microsoft.Xrm.Sdk.Linq.QueryProvider.GetQueryExpression(Expression expression, Boolean& throwIfSequenceIsEmpty, Boolean& throwIfSequenceNotSingle, Projection& projection, NavigationSource& source, List`1& linkLookups)
       bij Microsoft.Xrm.Sdk.Linq.QueryProvider.Execute[TElement](Expression expression)
       bij Microsoft.Xrm.Sdk.Linq.QueryProvider.GetEnumerator[TElement](Expression expression)
       bij Microsoft.Xrm.Sdk.Linq.Query`1.GetEnumerator()
       bij System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
       bij System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
       bij Enquete_Webform.Data.EnqueteGenerator.GetVragenforEnquete(Guid enGuid) in e:\VS\tfs_products\MS CRM\2011\Enquete\Enquete_Webform\Enquete_Webform\Data\EnqueteGenerator.cs:regel 49
  InnerException: 

Upvotes: 0

Views: 1945

Answers (3)

Nzall
Nzall

Reputation: 3565

After reading Daryl's comment about FetchXML, I've decided to convert my LINQ query to FetchXML, because this does support linked entity sorting. It now works as it should, and I get the results I need.

for completion, this is the fetchXML I ended up using:

<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='true'>
  <entity name='slfn_vraag'>
   <attribute name='slfn_vraagid' />
   <attribute name='slfn_vraag' />
   <attribute name='slfn_typevraag' />
   <attribute name='slfn_groep' />
   <order attribute='slfn_groep' descending='false' />
   <link-entity name='slfn_enquetevraag' from='slfn_vraag' to='slfn_vraagid' alias='aa'>
       <attribute name='slfn_volgorde'/>
       <order attribute='slfn_volgorde' descending='false' />
       <filter type='and'>
           <condition attribute='slfn_enquete' operator='eq' value='" + enGuid+@"' />
       </filter>
   </link-entity>
  </entity>
</fetch>

As an aside, None of the fields could be empty, because they were all primary and foreign keys in CRM, linking to other entities.

Upvotes: 1

Daryl
Daryl

Reputation: 18895

I'm guessing you have an ev.slfn_vraag that is null. Try adding a where statement to exclude those that have a null value

List<slfn_vraag> vraaglist = (from vr in _oContext.slfn_vraagSet
                              join ev in enquetevraaglist on vr.Id equals ev.slfn_vraag.Id
                              where ev.slfn_vragg.Id != null
                              orderby vr.slfn_Groep
                              select vr).ToList();

You could also have the null in the first statement as well:

var enquetevraaglist = (from ev in _oContext.slfn_enquetevraagSet
                        orderby ev.slfn_volgorde
                        where ev.slfn_enquete != null && ev.slfn_enquete.Id == enGuid
                        select ev)

I've created an extension method on the Entity Reference class that allows for nulls without erroring.

    /// <summary>
    /// Returns the Id of the entity reference or Guid.Empty if it is null"
    /// </summary>
    /// <param name="entity"></param>
    /// <returns></returns>
    public static Guid GetIdOrDefault(this EntityReference entity)
    {
        if (entity == null)
        {
            return Guid.Empty;
        }
        else
        {
            return entity.Id;
        }
    }

And as far as your question about sorting, CRM doesn't support sorting by a linked field, just keep that in mind.

Upvotes: 1

Koen
Koen

Reputation: 2571

Enumerable.OrderBy and Enumerable.ThenBy applied to the final vraaglist, might offer a solution to your case.

Upvotes: 1

Related Questions