这是正常的LINQ,此测试成功:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
namespace TestLINQ.Tests
{
[TestClass]
public class UnitTest2
{
[TestMethod]
public void TestGroupingAndOrdering()
{
var persons = GetTestPersons();
//Try get oldest Man and oldest Woman.
var Oldest = persons
.Where(p => p.Sex == TestGender.Male || p.Sex == TestGender.Female)
.OrderBy(p => p.DateOfBirth)
.GroupBy(p => p.Sex)
.Select(g => g.First());
//Try get youngest Man and youngest Woman.
var youngest = persons
.Where(p => p.Sex == TestGender.Male || p.Sex == TestGender.Female)
.OrderByDescending(p => p.DateOfBirth) //reversed sorting.
.GroupBy(p => p.Sex)
.Select(g => g.First());
Assert.AreEqual(Oldest.ToList().Count, 2);
Assert.AreEqual(youngest.ToList().Count, 2);
Assert.AreEqual(Oldest.First().Name, "Navya"); //Oldest Woman
Assert.AreEqual(Oldest.Last().Name, "Pranav"); //Oldest Man (Note: last() gets the second grouping)
Assert.AreEqual(youngest.First().Name, "Aditya"); // Youngest Man.
Assert.AreEqual(youngest.Last().Name, "Ananya"); // Youngest Woman.
}
public class TestPerson
{
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
public TestGender Sex { get; set; }
public TestPerson(string name, DateTime dob, TestGender sex)
{
Name = name;
DateOfBirth = dob;
Sex = sex;
}
}
public enum TestGender
{
Male,
Female,
Unknown
}
private List<TestPerson> GetTestPersons()
{
var list = new List<TestPerson>();
//LOL @ using indian names.
list.Add(new TestPerson("Advik", new DateTime(625909337000000000), TestGender.Male));
list.Add(new TestPerson("Navya", new DateTime(608385600000000000), TestGender.Female));
list.Add(new TestPerson("Ananya", new DateTime(626631005000000000), TestGender.Female));
list.Add(new TestPerson("Aditya", new DateTime(630061565000000000), TestGender.Male));
list.Add(new TestPerson("Veer", new DateTime(614074365000000000), TestGender.Male));
list.Add(new TestPerson("Ishaan", new DateTime(617700836000000000), TestGender.Male));
list.Add(new TestPerson("Pranav", new DateTime(610170773000000000), TestGender.Male));
list.Add(new TestPerson("Purusha", new DateTime(629134727000000000), TestGender.Unknown));
list.Add(new TestPerson("Avani", new DateTime(624015444000000000), TestGender.Female));
list.Add(new TestPerson("Pari", new DateTime(625879085000000000), TestGender.Female));
list.Add(new TestPerson("Nirguna", new DateTime(630489769000000000), TestGender.Unknown));
return list;
}
}
}
但是当您将数据插入数据库并尝试在使用LINQ to Entities时执行相同操作时,无论您应用哪种排序,似乎结果SQL都是相同的。
[TestMethod]
public void TestGroupingAndOrdering()
{
using (var context = new TestCRM())
{
var persons = context.Persons;
var result = persons
.Where(p => p.Sex == Gender.Male || p.Sex == Gender.Female)
.OrderBy(p => p.DateOfBirth) // REGARDLESS of what you do here, the resulting SQL is the same.
.GroupBy(p => p.Sex)
.Select(g => g.FirstOrDefault());
var EndResult = result.ToList();
Assert.AreEqual(EndResult.Count, 2);
}
}
有人可以帮帮我吗? - &GT;请告诉我在使用LINQ to Entities进行分组时如何保持排序。
答案 0 :(得分:7)
无论你在这里做什么,结果SQL都是一样的。
这是因为分组会破坏SQL中的顺序。 ORDER BY
子句在SQL SELECT
的语法中排在最后。即使您设法将其压缩到子查询中,该标准也允许RDBMS在GROUP BY
之后重新排序数据。与IQueryable<T>
一起使用的LINQ-to-Entities代码识别出这一点,并忽略GROUP BY
之前的所有排序。
要解决此问题,请将OrderBy
移动到分组后运行的查询部分,例如
var result = persons
.Where(p => p.Sex == Gender.Male || p.Sex == Gender.Female)
.GroupBy(p => p.Sex)
.Select(g => g.OrderBy(p => p.DateOfBirth).FirstOrDefault());
答案 1 :(得分:0)
使用上面的答案,我能够重新编写我的代码,从而产生了这个成功的测试:
[TestMethod]
public void TestGroupingAndOrdering()
{
using (var context = new TestCRM())
{
var persons = context.Persons;
//Try get oldest Man and oldest Woman.
var oldest = persons
.Where(p => p.Sex == Gender.Male || p.Sex == Gender.Female)
.GroupBy(p => p.Sex)
.Select(g => g.OrderBy(p => p.DateOfBirth));
//Try get youngest Man and youngest Woman.
var youngest = persons
.Where(p => p.Sex == Gender.Male || p.Sex == Gender.Female)
.GroupBy(p => p.Sex)
.Select(g => g.OrderByDescending(p => p.DateOfBirth));
var oldestMales = oldest.Where(x => x.All(q => q.Sex == Gender.Male)).FirstOrDefault();
var oldestFemales = oldest.Where(x => x.All(q => q.Sex == Gender.Female)).FirstOrDefault();
var oldestWoman = oldestFemales.FirstOrDefault();
var oldestMan = oldestMales.FirstOrDefault();
var youngestMales = youngest.Where(x => x.All(q => q.Sex == Gender.Male)).FirstOrDefault();
var youngestFemales = youngest.Where(x => x.All(q => q.Sex == Gender.Female)).FirstOrDefault();
var youngestWoman = youngestFemales.FirstOrDefault();
var youngestMan = youngestMales.FirstOrDefault();
Assert.AreEqual(oldestWoman.Name, "Navya"); //Oldest Woman
Assert.AreEqual(oldestMan.Name, "Pranav"); //Oldest Man
Assert.AreEqual(youngestMan.Name, "Aditya"); // Youngest Man
Assert.AreEqual(youngestWoman.Name, "Ananya"); // Youngest Woman
}
}
请注意:您不能只使用FirstOrDefault(),因为分组本身并未订购。这就是我需要这样做的原因:
var oldestFemales = oldest.Where(x => x.All(q => q.Sex == Gender.Female)).FirstOrDefault();
我接受了答案。非常感谢你!