C# 使用名称和值填充下拉列表的Linq Distinct()

C# 使用名称和值填充下拉列表的Linq Distinct(),c#,linq-to-sql,distinct,C#,Linq To Sql,Distinct,我正在尝试用制药公司填充一个下拉列表,如拜耳、Medley等。我从DB获得这些名称,这些名称在DB中重复,但id不同 我试图使用Linq Distinct,但我不想使用相等比较器。还有别的办法吗 我的下拉列表必须填写id和公司名称 我正在尝试类似的东西: var x = _partnerService .SelectPartners() .Select(c => new {codPartner = c.codPartner, name = c.n

我正在尝试用制药公司填充一个下拉列表,如拜耳、Medley等。我从DB获得这些名称,这些名称在DB中重复,但id不同

我试图使用Linq Distinct,但我不想使用相等比较器。还有别的办法吗

我的下拉列表必须填写id和公司名称

我正在尝试类似的东西:

var x = _partnerService
           .SelectPartners()
           .Select(c => new {codPartner = c.codPartner, name = c.name})
           .Distinct();
这显示了ddl中的重复公司


谢谢

Distinct在整个select上工作。如果在选择中包括c.codPartner,并且同一个c.name有两个不同的c.codPartner值,那么您将看到两行具有相同的c.name。

只需使用其他重载之一将自己的比较器传递到Distinct方法

(extension) IQueryable<T> IQueryable<T>.Distinct( IEqualityComparer<T> comparer )

如果不指定IEqualityComparer参数,那么它将只使用Object.ReferenceEquals,它查看对象的GetHashKey值。对于匿名类型,它们是唯一的

现在解决这个问题有点棘手,因为您无法为匿名类型编写IEqualityComparer。因此,您必须为问题创建一个真正的类型:

class Partner
{
    public int codPartner {get; set;}
    public string name {get; set;}
    public override int GetHashCode() { return name .GetHashCode();}
}

var x = _partnerService.SelectPartners()
        .Select(c => new Partner {codPartner = c.codPartner, name = c.name})
        .Distinct();

我不认为你可以用匿名类来实现这一点,但是如果你创建了一个数据对象,比如

    class Foo
{
    private int _ID;

    public int ID
    {
        get { return _ID; }
        set { _ID = value; }
    }
    private string _Name;

    public string Name
    {
        get { return _Name; }
        set { _Name = value; }
    }

}
    class FooComparer : IEqualityComparer<Foo>
{


    public bool Equals(Foo x, Foo y)
    {
        return x.Name == y.Name;
    }

    public int GetHashCode(Foo obj)
    {
        return obj.GetHashCode();
    }

}
您可以创建比较器对象,如

    class Foo
{
    private int _ID;

    public int ID
    {
        get { return _ID; }
        set { _ID = value; }
    }
    private string _Name;

    public string Name
    {
        get { return _Name; }
        set { _Name = value; }
    }

}
    class FooComparer : IEqualityComparer<Foo>
{


    public bool Equals(Foo x, Foo y)
    {
        return x.Name == y.Name;
    }

    public int GetHashCode(Foo obj)
    {
        return obj.GetHashCode();
    }

}

如果您没有通过IEqualityComparer告诉Distinc使用另一种方法,Distinc将使用GetHashCode。 您可以使用通用的equalitycomparer,如下所示:

public class GenericEqualityComparer<T> : IEqualityComparer<T>
{    
    private Func<T, T, Boolean> comparer;    

    public GenericEqualityComparer(Func<T, T, Boolean> comparer)    
    {        
        this.comparer = comparer;    
    }    

    #region IEqualityComparer<T> Implementation

    public bool Equals(T x, T y)    
    {        
        return comparer(x, y);    
    }    

    public int GetHashCode(T obj)    
    {
        return obj.GetHashCode();  
    }    

    #endregion
}
然后像这样使用

public static IEqualityComparer<YourType> MyComparer
{
   get
     {
      return new GenericEqualityComparer<YourType>((x, y) =>
       {
          return x.name.Equals(y.name);
        });
      }
}

下面的表达式将只选择不同的公司,并返回第一个id为的公司

partnerService.SelectPartners().GroupBy(p => p.Name).Select(g => g.First());

如果一个公司使用不同的id多次出现,而您希望它们只出现一次,那么应该显示什么id?第一个?没关系?这不会改变任何事。。。如果有几家公司名称相同但id不同,您会如何选择要使用的id?我同意-选择id将是一个问题。如果您想为每个应用程序指定一个特定的ID,那么使用distinct和EqualityComparer可能不是一个好办法。另外,请记住这里的否决票,原来的问题没有提到为不同结果中的每个项目选择特定的ID…ReferenceEquals不比较哈希代码,它比较引用。。。只有当两个引用指向同一个实例时,它才会返回true嗨Daniel!这正是我所需要的!谢谢-当我这样做时:dgvRecords.DataSource=来自dbContext.records中的g选择g.GroupByg=>g.ID.Selectg=>g.FirstOrDefault;I get:Message=不支持指定的方法。Source=MySql.Data。Entity@AndreMiranda您可以使用groupby并在主linq select的末尾选择,这非常有用@Daniel Brückner,TNX对于VB.net人员,使用.GroupByFunctionp p p.Name.SelectFunctiong g.首先还要确保导入System.Linq,否则您将无法在IGrouping类的select调用中获得第一个函数只是因为我一开始不理解这一点,它所做的是按名称对列表进行分组-[john,john,george,george,george]-然后只选择每个内部组中的第一个,并将其放入列表中。对不起,请问“g”来自哪里?@StarCub companys是一个IEnumerable。GroupBy接受并返回IEnumerable。选择中的每个项目都是一个iGroup。我使用了一个不同的名称,以使类型上的差异更加明显。