【问题标题】:LINQ query returns duplicate despite Distinct()尽管 Distinct() LINQ 查询返回重复
【发布时间】:2020-06-25 15:33:53
【问题描述】:

我得到以下绑定到 DropDownList 的查询;

if (!Page.IsPostBack)
        {
            var branchTags =
                (
                    from t in context.ContactSet
                    orderby t.py3_BranchArea
                    where t.py3_BranchArea != null
                    select new
                    {
                        BranchTagCode = t.py3_BranchArea,
                        BranchTag = (t.FormattedValues != null && t.FormattedValues.Contains("py3_brancharea") ? t.FormattedValues["py3_brancharea"] : null)
                    }
                ).Distinct();
            ddlBranchTags.DataSource = branchTags;
            ddlBranchTags.DataBind();
        }

由于某种原因,它仍然输出 2 行在视觉上是相同的。 CRM 中可能有两个同名的实体。但是,如果我在查询中使用 distinct 并且只返回 'py3_brancharea' 那么肯定应该在返回的实际记录上运行 Distinct 吗?

所以,这对我来说——以及我有限的 LINQ 知识——是因为这条线:

BranchTagCode = t.py3_BranchArea

但是,需要调用它才能调用 FormattedValues。

那么我如何才能获得完全基于“BranchTag”的一组不同的结果呢?

【问题讨论】:

    标签: c# linq linq-to-entities dynamics-crm-2011 dynamics-crm-online


    【解决方案1】:

    如果Distinct() 不起作用,则可能是特定类gethashcode()equals() 覆盖方法有问题,这些方法要么设置不正确,要么完全省略。在自定义类中,您很可能需要指定这些覆盖以使 Distinct() 和其他类似方法正常运行。

    您也可以尝试使用 where 或 any 子句来区分重复项。这可能是解决Distinct() 问题的方法。

    进一步解释如何使用自定义类设置Distinct() 方法。您需要在您正在搜索的类中设置覆盖方法GetHashCode()Equals()。无论如何,这些或对象级别的方法都应该存在于每个类中。要开始前往相关课程并输入以下内容:

    public override bool Equals(object obj) 然后 public override int GetHashCode()

    假设您在覆盖之前有这个简单的类:

    class foo{
       int H {get;set;}
       public foo(int _h){
            H = _h;
       }
    }
    

    它现在看起来像这样:

    class foo{
       int H {get;set;}
       int K {get;set;}
    
       public override bool Equals(object obj){
             if(obj == null) return false;
             foo test = (foo)obj);
             if(test == null) return false;
             
             if(this.H == obj.H && this.K == obj.K) return true;
       }
       public override int GetHashCode(){
             int hashH = H.GetHashCode();
             int hashK = K.GetHashCode();
    
             return hashH ^ hashK;
       }
    
       public foo(int _h){
            H = _h;
       }
    }
    

    现在您可以在包含 foo 类的 Ienumerable 类型上使用 Distinct(),如下所示:

     List<foo> FooList = new List<foo>(Collection of 9 Foos);
     var res = FooList.Distinct();
    

    【讨论】:

    • 任何一个例子。我是 LINQ 的新手,目前正在努力解决这个问题。谢谢。
    【解决方案2】:

    另一种对我有用但可能不适用于所有情况的更简单的方法是使用这种方法(GroupBy()First()):

    Finding Distinct Elements in a List

    他用FirstNameLastName 创建了一个List&lt;Customer&gt; customers。然后将它们全部按FirstName 分组,并从每个组中获取第一个元素!

    `
    List< Customer > customers = new List< Customer >;
    {
        new Customer {FirstName = "John", LastName = "Doe"},
        new Customer {FirstName = "Jane", LastName = "Doe"},
        new Customer {FirstName = "John", LastName = "Doe"},
        new Customer {FirstName = "Jay",  LastName = null},
        new Customer {FirstName = "Jay",  LastName = "Doe"}
    };
    `
    

    然后:

    `
    var distinctCustomers = customers.GroupBy(s => s.FirstName)
                                     .Select(s => s.First());
    `
    

    在我的情况下,我不得不使用FirstOrDefault()

    【讨论】:

      【解决方案3】:

      有没有可能这两个结果不同,它们的分支标签代码和分支标签是一样的吗?

      您可以实现一个自定义相等比较器并将其传递给 distinct() 以便它只比较您想要的字段?由于您的选择语句中的匿名类型,这有点困难,但this 答案有办法解决这个问题。

      【讨论】:

      • 是的,我相信它是。这就是我发帖的原因。希望能在第二个领域找到一种与众不同的方法。该链接看起来很有潜力。谢谢。
      • 实际上,不幸的是,该链接不起作用。此外,在 CRM 中检查字段不重复。所以不知道如何在结果中选择一个不同的。
      • 您能否提供更多代码给我们一个展示问题的示例?导致问题的结果是什么?如果你用一个包含问题的两个对象的简单列表替换实体上下文,你能重现它吗?
      • 基本上它是区域办事处的列表,以及它们在 CRM 中的对应 ID。由于某种原因,其中一个分支具有另一个实例,该实例具有单独的 id 但名称相同。我实际上在 CRM 中看不到这个其他分支,所以它看起来像是附加到某人帐户的某种遗物。因此,虽然所有返回的分支 ID 都不同,但它们的两个分支名称相同。我需要删除这个额外的,但不想硬编码(例如手动删除这个)。
      • 你的意思是BranchTagCodes不同,但是两个结果的BranchTags是一样的?
      【解决方案4】:

      匿名类型的默认相等比较区分大小写。您期望的返回值是否有不同的大小写?正如马特建议的那样,您可能希望在自定义类上查看自定义 IEqualityComparer 实现。

      【讨论】:

      • 相同的大小写,所以不知道为什么会导致问题。
      【解决方案5】:

      我从

      更改了我的代码
      .Distinct().ToList();
      

      .ToList().Distinct().ToList();
      

      现在它可以避免重复了。不知道是什么原因。

      【讨论】:

        【解决方案6】:

        实体对象具有不唯一的定义键的另一种可能性。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-02
          • 1970-01-01
          • 2021-01-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多