LINQ Group By和NOT in

时间:2011-03-29 19:38:55

标签: linq

我有一个类似下面的架构(这是一个简化的示例,所以请忽略明显的架构问题):

table Books
{
    string bookId
}

table students_books
{
    string studentname
    string bookId
}

目的是找出阅读量少于500次的书籍。不幸的是,我无法将这一点记在书桌上。

我正在编写这样的查询:

from book in Books
    where !(from student in students_books
        group student by student.bookId into GroupedPerStudent
        where GroupedPerStudent.Count() >= 500 
        select new { bookname = GroupedPerStudent.Key }).Contains(book.bookid)
    select book 

我在Contains()上收到了编译错误。查询有什么问题?

  

无法从使用中推断出方法'System.Linq.Enumerable.Contains< TSource>(System.Collections.Generic.IEnumerable< TSource>,TSource)'的类型参数。尝试明确指定类型参数。

2 个答案:

答案 0 :(得分:5)

您的嵌套查询正在选择匿名类型 - 您应该选择图书ID:

from book in Books
  where !(from student in students_books
          group student by student.bookId into GroupedPerStudent
          where GroupedPerStudent.Count() >= 500 
          select GroupedPerStudent.Key).Contains(book.bookid)
select book;

但我会以更积极的方式表达它 - 实际上是用两个单独的陈述来使它更清晰:

var rarelyRead = from student in student_books
                 group student by student.bookId into grouped
                 where grouped.Count() < 5000
                 select grouped.Key;

var query = Books.Where(book => rarelyRead.Contains(book.book_id));

编辑:或者,根据Snowbear的建议,使用连接,我们将使用查询延续以获得乐趣:

var query = from student in student_books
            group student by student.bookId into grouped
            where grouped.Count() < 5000
            select grouped.Key into rarelyRead
            join book in Books on rarelyRead equals book.book_id
            select book;

答案 1 :(得分:3)

您在嵌套查询中选择匿名类型,将其替换为select GroupedPerStudent.Key

   ...
   where GroupedPerStudent.Count() >= 500 
         select GroupedPerStudent.Key).Contains(book.bookid)

虽然我会重写整个查询:

var popularBooks = students_books
                      .GroupBy(b => b.bookId)
                      .Where(g => g.Count() >= 500)
                      .Join(Books, students_book => students_book.Key, b => b.bookId,
                                  (students_books, book) => book);