Entity Framework子查询

10

大家好,我是新手Entity Framework,我一直在尝试解决一个问题。我的数据库有4个实体:用户、组、书和阅读列表。用户可以加入一个组,一个组包含由阅读列表定义的书籍。我正在尝试显示特定组的书籍列表,SQL语句如下:

SELECT * FROM Books b
WHERE b.Id IN (
    SELECT BookID FROM ReadingList rl
        WHERE rl.GroupID = '3')

我通过从UserRepository查询当前用户来确定正在搜索的GroupID,目前“按组获取图书”的方法看起来是这样的:

// Get books by group
public IQueryable<Book> GetGroupBooks(string username)
{
    UserRepository userRepository = new UserRepository();
    int groupId = userRepository.GetUserGroupId(username);

    IQueryable<Book> q = from b in entities.Books 
                         where b.Id == 7 // temp - these values should be determined by 
                                         // rl in entites.ReadingList select rl.BookID where r.GroupID == groupID
                         select b;

    return q;
}

显然这只是一个临时措施,仅返回一本书,但我已经包含它作为参考。在这里任何帮助或建议将不胜感激。

谢谢


你的Book和ReadingList之间有外键吗? - Nix
2个回答

7

个人认为有一个更好的解决方案(未经测试):

首先按GroupdID从ReadList中进行选择,然后在BookID上与books进行连接。

IQueryable<Book> q = 
       from rl in entities.ReadingList
       join b in entities.Books on rl.BookID equals b.BookID
       where rl.GroupdID ==groupID
       select b;

var books = q.ToList()

如果您有任何问题,请告诉我。


+1 更详细的方法。个人更喜欢简写方式。:) 但是为什么要使用 Distinct - Mayank
你是对的,出于某种原因我在想阅读列表...不需要它。 - Nix
“Distinct” 的作用是去重书籍,因为它可能会被返回多次。 - Nekresh

6

我还没有测试过,但希望它能够正常工作。

entities.Books.Where(
b => entities.ReadingList.
Where(rl => rl.GroupId == groupId).
Select(rl => rl.BookId).
Contains(b.BookId)
)

你可能需要解释一下你在这里做什么,因为它并不高效。你正在执行一个子查询,但是你将会为每本书执行子查询。 - Nix
我应该添加ReadingList包含两个外键,一个指向Books,另一个指向Groups。ReadingList包含一个复合主键(BookID和GroupID),确保同一组中没有书籍出现超过一次。 - Apollo
据我所知,编译器足够聪明,能够理解如何优化处理过程。因此,子查询不会为每本书执行一次,而是首先在内存中检查特定的分组。 - Mayank
1
编译器并不是它在后台所执行的EF操作。首先会从数据库中提取数据,其余部分将会是内存中的查询。我确定你不会有大量数据,所以这不会成为问题,但我觉得应该注意到这一点。 - Nix
刚刚用 EF 5 进行了测试,生成的查询语句在优化方面与“where in (Select..)”完全相同,非常高效。 - Jonathan Levison

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接