简体   繁体   English

LINQ选择不同的集合并检索不同的列

[英]LINQ select distinct set and retrive different column

I want to be able to execute the following query: 我希望能够执行以下查询:

select distinct studentname, subject, grade from studenttable;

The student table has the following fields: 学生表具有以下字段:

studentid
studentname
subject
grade

The linq query I have now is: 我现在使用的linq查询是:

var students=dc.Select(s => new {s.studentname, s.subject, s.grade}).Distinct();

dc is the data context. dc是数据上下文。

This query works, but how do I get the student id while still satisfying the distinct condition on the studentname, subject, grade set? 该查询有效,但是如何在仍满足学生studentname, subject, grade设置的特殊条件的同时,获得学生id

The issue here is that you've collected three properties of the necessary data which, while they will suffice to pass through Distinct , don't have any link back to their original data, and any such link would break the default implementation of Distinct . 这里的问题是,您已经收集了必要数据的三个属性,尽管这些属性足以通过Distinct传递,但没有任何链接返回其原始数据,并且任何此类链接都会破坏Distinct的默认实现。

What you CAN do, however, is to use the overload of distinct which takes an IEqualityComparer . 但是,您可以做的是使用带有IEqualityComparer的distance的重载。 This will allow you to compare for equality only on the desired fields, while running Distinct over the entire collection. 这将允许您在整个集合上运行Distinct时仅在所需字段上进行相等性比较。

var students = dc
    .AsEnumerable() // In case you're using a linq-to-sql framework, this will ensure the query execute in-memory
    .Distinct(new SpecialtyComparer());

//...

public class SpecialtyComparer : IEqualityComparer<StudentTable>
{
    public int GetHashCode(StudentTable s)
    {
        return s.studentname.GetHashCode()
            && s.subject.GetHashCode()
            && s.grade.GetHashCode();
    }

    public bool Equals(StudentTable s1, StudenTable s2)
    {
        return s1.studentname.Equals(s2.studentname)
            && s1.subject.Equals(s2.subject)
            && s1.grade.Equals(s2.grade);
    }
}

I believe your design is broken, but I'll answer your specific question.... 我相信您的设计已损坏,但我会回答您的特定问题。

I'm assuming you're trying to group by name, subject and grade, and retrieve the first representative student of each group. 我假设您正在尝试按名称,主题和年级分组,并检索每个分组的第一位代表性学生。

In this case, you can group by Tuples. 在这种情况下,您可以按元组进行分组。 A tuple will give you an Equals and GetHashCode method for free, so can be used in Group operations. 元组将免费为您提供EqualsGetHashCode方法,因此可以在组操作中使用。

IEnumerable<Student> distinctStudents = students
                                           .AsEnumerable()
                                           .GroupBy(s => Tuple.Create
                                                               (
                                                                   s.studentname, 
                                                                   s.subject, 
                                                                   s.grade
                                                               )
                                                          )
                                           .Select(g => g.First()); /// Returns the first student of each group

Here is a dot net fiddle example: 这是一个点网小提琴示例: https://dotnetfiddle.net/7K13DJ https://dotnetfiddle.net/7K13DJ

When doing a Distinct() on a list of objects, you are aggregating those rows into a smaller number of rows, discarding any duplicates. 在对象列表上执行Distinct()时,将这些行聚合为较少的行数,并丢弃所有重复项。 So, your result will not have the studentid anymore. 因此,您的结果将不再有studentid To preserve the studentid property, you need to use a GroupBy . 要保留studentid属性,您需要使用GroupBy This will return to you your key (a student of studentname , subject , grade ), and a list of original rows. 这将返回给您您的密钥( studentnamesubjectgrade的学生)和原始行的列表。 You can see an example in this question here: ( GroupBy and count the unique elements in a List ). 您可以在此问题中看到一个示例:(使用GroupBy并计算List中的唯一元素 )。

You will have a list of studentids to choose from, since there might be many rows with the same studentname , subject , and grade . 您将有一个studentids列表可供选择,因为可能会有许多行具有相同的studentnamesubjectgrade (Otherwise you would not be doing a distinct -- they would be unique and the tuple { sudentname, subject, grade } would be a natural key ). (否则,您将不会做独特的操作-它们将是唯一的,并且tuple { sudentname, subject, grade }将是自然键 )。 So the question you may need to ask yourself is "Which studentid do I need?" 因此,您可能需要问自己的问题是“我需要哪个学生证?”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM