在动态 CRM 2011 Linq 查询中按双倍排序

本文关键字:排序 查询 动态 CRM 2011 Linq | 更新日期: 2023-09-27 18:31:20

我正在为 CRM 2011 开发一个调查模块,CRM 用户可以在其中使用不同类型的多个问题进行调查,并要求联系人使用 Azure 上的动态网页回答这些问题。到目前为止,我已经完成了大约 90% 的内容,只需要添加一些涉及数据管理的小更改。

我目前正在优化的部分涉及整理我的问题。我在CRM中有2个实体:调查问题和问题。问题是指调查中的实际问题,而调查问题是一个 N-N 关系实体,具有一些附加字段,因此我们可以在不同的调查中重复使用问题。我在"问题"中有一个字段"groep",用于指示是否应该将一个问题与表单上的另一个问题分组。我还有另一个字段,"调查问题"中的"volgorde",用于指示问题的顺序。我希望将所有具有相同"组"的问题一起显示,然后按sortorder字段对组内的任何问题(以及作为单独组的未分组问题)进行排序。所以我基本上需要在 2 个不同表中的 2 个字段上排序,这似乎很棘手。

这是我当前使用的代码。我在 vraaglist 的连接上收到一个空引用异常,这很奇怪,因为两个 vr。ID 和ev.slfn_vraag。Id 在相关行中包含数据。我不认为这是由于 orderby,因为上面的注释代码有效(但我不能简单地将 ev.volgorde 添加到我的 orderby 中,因为他抱怨这一点。

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;
    }

代码编译时没有错误,但是当我运行它时,我在问题查询上得到一个 NullReferenceException。 有人对如何解决这个问题有任何想法吗?

编辑:VS2012的异常详细信息如下。

  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: 

在动态 CRM 2011 Linq 查询中按双倍排序

Enumerable.OrderBy 和 Enumerable.ThenBy 应用于最终vraaglist ,可能会为您的情况提供解决方案。

我猜你有一个空ev.slfn_vraag。 尝试添加 where 语句以排除具有空值的语句

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();

您也可以在第一个语句中使用 null:

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

我在实体引用类上创建了一个扩展方法,该方法允许空值而不会出错。

    /// <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;
        }
    }

至于您关于排序的问题,CRM不支持按链接字段排序,请记住这一点。

在阅读了 Daryl 关于 FetchXML 的评论后,我决定将我的 LINQ 查询转换为 FetchXML,因为这确实支持链接实体排序。它现在可以正常工作,我得到了我需要的结果。

为了完成,这是我最终使用的 fetchXML:

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

顺便说一句,没有一个字段可以为空,因为它们都是CRM中的主键和外键,链接到其他实体。