2

我正在尝试为列中的每个唯一项目获取 Top(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;
     }

不幸的是,我收到了这个错误。

      Query Source could not be identified:
      ItemName = g, ItemType = System.Linq.IGrouping`2

代码中此时触发异常

  var inspections = _inspectionRepository.GetLatestInspectionDatesForAllRestaurants(2).ToList(); 

我错过了什么?

编辑

运行测试后,我确认查询在 LINQ-To-Objects 中运行良好。是否有可能 NHibernate.Linq 在这方面仍然不完整?我做了一个稍微不同的查询(如下)并得到了一个未实现的异常。

       .GroupBy(r=> r.RestaurauntName)
                            .Select(g => g.First()).Take(5)

如果我从最后删除 Take(5),我会得到以下信息(提醒这是一个示例,我的 PK 在我的真实案例中是 Id)。

  {"Column '.Id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause."}

我需要学习使用创建标准吗?

4

2 回答 2

1

好吧,我得到了我需要生成的 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;
}

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

于 2013-06-18T16:05:30.563 回答
0
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 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();
}

这是第 3 个选项,它的性能很差,但应该从等式中消除 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();
}
于 2013-06-14T21:51:42.173 回答