【问题标题】:double order by in Dynamics CRM 2011 Linq queryDynamics CRM 2011 Linq 查询中的双重订购
【发布时间】:2013-09-13 09:14:56
【问题描述】:

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

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

这是我目前正在使用的代码。我在 vraaglist 的连接上得到一个 nullreferenceexception,这很奇怪,因为 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: 

【问题讨论】:

    标签: c# linq dynamics-crm-2011


    【解决方案1】:

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

    【讨论】:

    • 这不起作用,因为 OrderBy 和 ThenBy 要求要排序的字段是所选表的一部分。因为我的 1 个字段不是来自所选表,所以它不起作用。
    • 作为后续:我尝试在 ToList() 之前和之后添加我的“OrderBy”,甚至只是删除所有 orderby 语句,这 3 个选项都没有给出不同的结果。
    【解决方案2】:

    我猜你有一个 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 不支持按链接字段进行排序,请记住这一点。

    【讨论】:

    • 我已经添加了这些 != null 检查,但它们并没有解决问题。至于排序问题,我想通过首先对 enquetevragen 进行排序,然后使用排序后的 IQueryable 来获得正确的问题,然后对 vragenlist 进行排序来避开那个项目符号。还是我不能以这种方式组合 LINQ 查询?
    • @nzall 就您的空错误而言,原因只有 3 种可能性。 _oContext 为空,slfn_enquete 为空或 slfn_vraag。一片空白。如果您有任何插件正在读取,它们也可能会引发异常,但从堆栈跟踪来看,我猜这不是问题。
    • @nzall 就排序而言,您可能必须将 IQueryable 更改为列表。这样,CRM 会执行 2 个查询,而不是一次只执行 1 个。
    • CRM 是否完全不支持链接字段排序,或者是否可以使用 QueryExpression 使用链接字段进行排序?还是通过 FetchXML?还是根本不支持?
    • @nzall QueryExpressions 不支持对链接实体进行排序,并且 LINQ 在后台使用查询表达式,因此它也不支持它。但是 Fetch XML 确实支持它:nishantrana.wordpress.com/2012/04/27/…
    【解决方案3】:

    在阅读了 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 中的主键和外键,链接到其他实体。

    【讨论】:

    • 为什么外键不能为空?
    • 因为我使用对话过程创建调查,以确保所有字段都填充有有效密钥。你永远不会有一个 vraag 为空的 enquetevraag,因为 enquetevragen 是与 vragen 一起生成的。所以它不完全是因为它是一个外键,而是因为设计意味着它不能为空。
    • 啊,前端强制了,但是数据库里没有强制的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多