MVC EF LINQ - 区别不起作用

时间:2016-07-06 10:13:15

标签: c# asp.net-mvc entity-framework linq

我有以下查询期望根据所选学校仅从实体中检索唯一值:

var semesters = (from cou in db.Courses
    join sem in db.Semesters on cou.SemesterID equals sem.ID
    where cou.FacultyID == id 
    select new SemestersModel {
        SemesterID = sem.ID,
        SemesterText = sem.Semester })
    .Distinct()
    .ToList();

但是它会返回实体课程中包含的所有学期

  • 第一学期,第一学期,第一学期,第二学期,第二学期......等。 等

请帮助我只抓住不同的学期名称,例如

  • 第一学期,第二学期等

P.S。我的问题与此问题不同Distinct in Linq based on only one field of the table

4 个答案:

答案 0 :(得分:3)

您在创建Distinct后使用SemestersModel,如果该类型未覆盖Equals + GetHashCode,则只会比较引用,在这种情况下是不同的。

因此,要么覆盖这些方法,请为IEqualityComparer<SemestersModel>提供自定义Linq-To-EntitiesLinq-To-SqlDistinct不支持),或者只使用Distinct匿名类型:

var semesters = from cou in db.Courses
                join sem in db.Semesters 
                on cou.SemesterID equals sem.ID
                where cou.FacultyID == id 
                select new { SemesterID = sem.ID, SemesterText = sem.Semester };
List<SemestersModel> uniqueSemesterList = semesters
    .Distinct()   
    .Select(x => new SemestersModel {
        SemesterID = x.SemesterID, 
        SemesterText = x.SemesterText })
    .ToList(); // due to deferred execution only now the query above will be executed together with Distinct

此查询可以转换为有效的SQL(省略joinwhere):

SELECT DISTINCT SemesterID, SemesterText FROM dbo.Semesters 

将执行查询,并在内存中创建唯一的SemestersModel实例以填充列表。

答案 1 :(得分:2)

如果您按照要分隔的字段对学期进行分组,则选择该组的第一个,现在您可以将结果投影到SemestersModel实例中。

(from cou in db.Courses
    join sem in db.Semesters on cou.SemesterID equals sem.ID
    where cou.FacultyID == id 
    select sem)
    .GroupBy(sem => sem.Semester)
    .Select(g => g.FirstOrDefault())
    .Select(sem => new SemestersModel {
        SemesterID = sem.ID,
        SemesterText = sem.Semester 
    })
    .ToList();

答案 2 :(得分:1)

不同的方法使用IEqualityComparer来比较对象。因此,如果您使用Distinct()过滤记录,则可以创建一个实施IEqualityComparer的比较器并将其传递给Distinct()

这是一个例子。

class Employee
{
    public int Id { get; set; }
    public String Name { get; set; }
}

class EmpEqualityComparer : IEqualityComparer<Employee>
{
    public bool Equals(Employee x, Employee y)
    {
        if (x.Id == y.Id && x.Name == y.Name)
            return true;
        else
            return false;
    }

    public int GetHashCode(Employee obj)
    {
        int hCode = obj.Id;
        return hCode.GetHashCode();
    }
}

现在你可以测试一下。

List<Employee> emp = new List<Employee>();
        emp.Add(new Employee() { Id = 123, Name = "Saket"});
        emp.Add(new Employee() { Id = 123, Name = "Saket" });
        emp.Add(new Employee() { Id = 123, Name = "Saket" });
        emp.Add(new Employee() { Id = 123, Name = "Saket" });
        emp.Add(new Employee() { Id = 123, Name = "Saket" });
        emp.Add(new Employee() { Id = 123, Name = "Saket" });
        emp.Add(new Employee() { Id = 123, Name = "Saket" });

        EmpEqualityComparer eqi = new EmpEqualityComparer();

        var employees = (from e in emp
                         select new Employee { Id = e.Id, Name = e.Name }).Distinct(eqi).ToList();

返回单个记录。 enter image description here

希望它有所帮助。

答案 3 :(得分:0)

这是不可能的......
您需要让SemesterModel类继承IEquatable。并覆盖两个函数Equals和GetHashCode。

public class SemestersModel  : IEquatable<SemestersModel >{
public string SemesterID  { get; set; }
public string SemesterText  { get; set; }
public bool Equals(SemestersModel comp)
{
    if (SemesterID == comp.SemesterID && SemesterText == comp.SemesterText)
        return true;
    return false;
}
public override int GetHashCode()
{
    int hSemesterID = SemesterID == null ? 0 : SemesterID.GetHashCode();
    int hSemesterText = SemesterText == null ? 0 : SemesterText.GetHashCode();

    return hSemesterID ^ hSemesterText;
}}