C# 取LINQ中每个分组项目的顶部(X)

C# 取LINQ中每个分组项目的顶部(X),c#,linq,nhibernate,C#,Linq,Nhibernate,我试图为一列中的每一个独特的项目获取顶部(X)记录 例如: Inspections InspectionId | RestaurauntName | InspectionDate ------------------------------------------------ 1 Mom&Pop 10/10/12 2 SandwichesPlace 10/10/12 3 Mom&a

我试图为一列中的每一个独特的项目获取顶部(X)记录

例如:

Inspections
InspectionId | RestaurauntName | InspectionDate
------------------------------------------------
1               Mom&Pop           10/10/12
2               SandwichesPlace   10/10/12
3               Mom&Pop           10/10/11
4               SandwichesPlace   10/10/11
5               Mom&Pop           10/10/10
6               SandwichesPlace   10/10/10
7               BurgerPlace       10/10/11
8               BurgerPlace       10/10/09
9               BurgerPlace       10/10/08
如果我将“2”的值作为参数传递,我希望返回记录1、2、3、4、7、8

在这个示例片段中,我试图为每个“restaurantName”获取一些记录

    public IQueryable<Inspections> 
    GetLatestInspectionDatesForAllRestaurants(int numRecords) {

    IQueryable<Inspections> inspections= _session.Query<Inspections>()
                            .GroupBy(r=> r.RestaurauntName)
                            .SelectMany(g => g
                                            .OrderBy(r => r.InspectionDate)
                                            .Take(numRecords));

            return inspections;
     }
异常在代码中的这一点触发

  var inspections = _inspectionRepository.GetLatestInspectionDatesForAllRestaurants(2).ToList(); 
我错过了什么

编辑 运行测试后,我确认查询在LINQtoObjects中运行良好。有没有可能是NHibernate,Linq在这方面还不完善?我做了一个稍微不同的查询(如下),得到了一个未实现的异常

       .GroupBy(r=> r.RestaurauntName)
                            .Select(g => g.First()).Take(5)
如果我从结尾处删除Take(5),我会得到以下提示(这是一个示例,我的PK是真实案例中的Id)

我需要学习使用创建标准还是什么吗?

公共类检查{
public class Inspections{
    public int InspectionId {get;set;}
    public string RestaurantName {get;set;}
    public DateTime InspectionDate {get;set;}
}
void Main()
{
    var result=GetLatestInspectionDatesForAllRestaurants(2);
    result.Dump();
}
public IQueryable<Inspections> 
    GetLatestInspectionDatesForAllRestaurants(int numRecords) {
        var i = new[]{
        new Inspections{InspectionId=1,RestaurantName="Mom&Pop",InspectionDate=DateTime.Parse("10/10/12")},
        new Inspections{InspectionId=2,RestaurantName="SandwichesPlace",InspectionDate=DateTime.Parse("10/10/12")},
        new Inspections{InspectionId=3,RestaurantName="Mom&Pop",InspectionDate=DateTime.Parse("10/10/11")},
        new Inspections{InspectionId=4,RestaurantName="SandwichesPlace",InspectionDate=DateTime.Parse("10/10/11")},
        new Inspections{InspectionId=5,RestaurantName="Mom&Pop",InspectionDate=DateTime.Parse("10/10/10")},
        new Inspections{InspectionId=6,RestaurantName="SandwichesPlace",InspectionDate=DateTime.Parse("10/10/10")},
        new Inspections{InspectionId=7,RestaurantName="BurgerPlace",InspectionDate=DateTime.Parse("10/10/11")},
        new Inspections{InspectionId=8,RestaurantName="BurgerPlace",InspectionDate=DateTime.Parse("10/10/09")},
        new Inspections{InspectionId=9,RestaurantName="BurgerPlace",InspectionDate=DateTime.Parse("10/10/08")}
    };
    var result=i.GroupBy(g=>g.RestaurantName).SelectMany(g=>g.OrderByDescending(d=>d.InspectionDate).Take(2));
    return result.AsQueryable();
    }
public int-InspectionId{get;set;} 公共字符串RestaurantName{get;set;} 公共日期时间检查日期{get;set;} } void Main() { var结果=GetLateStInspectionDatesForallResults(2); result.Dump(); } 公共图书馆 GetLatestInspectionDatesForAllRestaurants(国际数字记录){ var i=新[]{ 新检查{InspectionId=1,RestaurantName=“Mom&Pop”,InspectionDate=DateTime.Parse(“10/10/12”)}, 新检查{InspectionId=2,RestaurantName=“SandwichesPlace”,InspectionDate=DateTime.Parse(“10/10/12”)}, 新检查{InspectionId=3,RestaurantName=“Mom&Pop”,InspectionDate=DateTime.Parse(“10/10/11”)}, 新检查{InspectionId=4,RestaurantName=“SandwichesPlace”,InspectionDate=DateTime.Parse(“10/10/11”)}, 新检查{InspectionId=5,RestaurantName=“Mom&Pop”,InspectionDate=DateTime.Parse(“10/10/10”)}, 新检查{InspectionId=6,RestaurantName=“SandwichesPlace”,InspectionDate=DateTime.Parse(“10/10/10”)}, 新检查{InspectionId=7,RestaurantName=“BurgerPlace”,InspectionDate=DateTime.Parse(“10/10/11”)}, 新检查{InspectionId=8,RestaurantName=“BurgerPlace”,InspectionDate=DateTime.Parse(“10/10/09”)}, 新检查{InspectionId=9,RestaurantName=“BurgerPlace”,InspectionDate=DateTime.Parse(“10/10/08”)} }; var result=i.GroupBy(g=>g.RestaurantName)。选择many(g=>g.OrderByDescending(d=>d.InspectionDate)。取(2); 返回结果。AsQueryable(); }
这运行得很好,所以我假设您对原始可查询项的生存期有问题。请尝试以下操作:

public IQueryable<Inspections> 
  GetLatestInspectionDatesForAllRestaurants(int numRecords)
{

  IQueryable<Inspections> inspections= _session.Query<Inspections>()
                        .GroupBy(r=> r.RestaurauntName)
                        .SelectMany(g => g
                                        .OrderByDescending(r => r.InspectionDate)
                                        .Take(numRecords));

  return inspections.ToList().AsQueryable();
}
公共IQueryable
GetLatestInspectionDatesForAllRestaurants(国际数字记录)
{
IQueryable检查=_session.Query()
.GroupBy(r=>r.RestaurauntName)
.SelectMany(g=>g
.OrderByDescending(r=>r.InspectionDate)
.拿(numRecords));
退货检验.ToList().AsQueryable();
}
下面是第三个选项,它的性能很差,但应该从等式中删除NHibernate:

public IQueryable<Inspections> 
  GetLatestInspectionDatesForAllRestaurants(int numRecords)
{

  IQueryable<Inspections> inspections= _session.Query<Inspections>().ToList()
                        .GroupBy(r=> r.RestaurauntName)
                        .SelectMany(g => g
                                        .OrderByDescending(r => r.InspectionDate)
                                        .Take(numRecords));

  return inspections.ToList().AsQueryable();
}
公共IQueryable
GetLatestInspectionDatesForAllRestaurants(国际数字记录)
{
IQueryable检验=\u session.Query().ToList()
.GroupBy(r=>r.RestaurauntName)
.SelectMany(g=>g
.OrderByDescending(r=>r.InspectionDate)
.拿(numRecords));
退货检验.ToList().AsQueryable();
}

我得到了我需要生成的SQL,这需要一些研究等等。我确信我最初的问题与LINQ和NHibernate有关,尽管Robert最后提出的问题在技术上是正确的

由于IQueryable的性质,这将生成一个SQL脚本,直到必要时才进行枚举。SQL本身生成“Where Exists”子句

public IQueryable<Inspections> 
GetLatestInspectionDatesForAllRestaurants(int numRecords)
{
     var subQuery =  _session.Query<Inspections>()
     .OrderByDescending(x => x.InspectionDate);

     var inspections = _session.Query<Inspections>()
                        .Where(x => subQuery.Where(y => y.InspectionDate == 
                               x.InspectionDate).Take(numRecords).Contains(x))
                        .OrderBy(x => x.WellDataId);
    return inspections;
}
公共IQueryable
GetLatestInspectionDatesForAllRestaurants(国际数字记录)
{
var子查询=_session.Query()
.OrderByDescending(x=>x.InspectionDate);
var检查=_session.Query()
.Where(x=>subQuery.Where(y=>y.InspectionDate==
x、 检查日期)。取(numRecords)。包含(x))
.OrderBy(x=>x.WellDataId);
退货检查;
}

就是这样,希望它最终能帮助其他人。

IQueryable检验
更改为
var检验
,看看是否相同。是的,是相同的Bob,好的建议注意,我将OrderBy更改为OrderByDescending,因此您可以获取最新的numRecords值,而不是最早的numRecords值。这仅仅是因为Seth had函数返回IQueryable。嗨,Robert,我同意此函数应该运行,但我仍然会得到错误。我遵循了您的第一个示例,这个查询在新的列表“i”中也对我有效。它必须与Linq的NHibernate实现相关,不是吗?可能是。我从来没有真正使用过NHibernate。这可能是他们的LINQ实现中的一个bug,也可能是他们的实现中我不知道的一些特定的东西。我将添加第三个选项,它将运行得非常糟糕,但应该避开任何NHibernate问题,请注意,它的性能会很差。
public IQueryable<Inspections> 
  GetLatestInspectionDatesForAllRestaurants(int numRecords)
{

  IQueryable<Inspections> inspections= _session.Query<Inspections>().ToList()
                        .GroupBy(r=> r.RestaurauntName)
                        .SelectMany(g => g
                                        .OrderByDescending(r => r.InspectionDate)
                                        .Take(numRecords));

  return inspections.ToList().AsQueryable();
}
public IQueryable<Inspections> 
GetLatestInspectionDatesForAllRestaurants(int numRecords)
{
     var subQuery =  _session.Query<Inspections>()
     .OrderByDescending(x => x.InspectionDate);

     var inspections = _session.Query<Inspections>()
                        .Where(x => subQuery.Where(y => y.InspectionDate == 
                               x.InspectionDate).Take(numRecords).Contains(x))
                        .OrderBy(x => x.WellDataId);
    return inspections;
}