2016-11-28 8 views
9

をグループ化する際のソート保つこれは、通常のLINQであり、このテストは成功します。LINQ 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を使用するときに同じことをしようとすると、あなたが適用する並べ替えに関係なく、結果として得られる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); 
     }    
    } 

誰か助けてもらえますか? - > LINQ to Entitiesを使用するときにグループ分けするときのソート方法を教えてください。

+0

'GetTestPersons()'メソッドは 'context.Persons'と同じ結果を返しますか? –

答えて

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()); 
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(); 

私は答えを以下に受け入れます。どうもありがとうございました!

関連する問題