c# - NHibernate to Linq 获取没有出过书的作者

标签 c# sql linq nhibernate

为了简化说明,我以作者和书籍为例。作者 - 书籍具有一对多关系,即一位作者可以写多本书。映射是使用 FluentHibernate 完成的,没有什么特别之处。

我正在尝试查询还没有写任何书的作者。但是当查看在 NHibernate Profiler 中生成的查询时,这不是我所期望的。你们能解决这个错误吗

我期望的结果来自下面的查询

select a.AuthorName
       ,a.AuthorId from Authors a left outer join Books b on a.AuthorId = b.AuthorId
where b.AuthorId is null

实际生成的查询如下

SELECT AuthorId,
       AuthorName,
       CreatedAt
FROM   Authors
WHERE  AuthorId is null

为上述提供的映射

public class AuthorsMap : ClassMap<Author>
{

    public AuthorsMap()
    {
        Table("Authors");
        LazyLoad();
        Id(x => x.AuthorId).GeneratedBy.Identity().Column("AuthorId");
        Map(x => x.AuthorName).Column("AuthorName").Not.Nullable();
        Map(x => x.CreatedAt).Column("CreateDatetime").Not.Nullable();
        HasMany(x => x.Books).KeyColumn("AuthorId");
    }
}

上面是为作者提供的映射,下面是为书籍提供的映射

public class BooksMap : ClassMap<Books>
{
    public BooksMap()
    {
        Table("Books");
        LazyLoad();
        Id(x => x.BookId).GeneratedBy.Identity().Column("BookId");
        References(x => x.Author).Column("AuthorId");
        Map(x => x.BookName).Column("BookName").Not.Nullable();
    }
}

查询调用如下

Session.Linq<Author>().Where(author => author.Books == null).ToList();

上述的另一种形式导致了对象引用错误

Session.Linq<Author>().Where(author => author.Books.Count == 0).ToList();

性能问题:

来自@Ocelot20 的答案有效,但正在生成 N + 1 个查询以查找记录

Session.Linq<Author>().Where(author => !author.Books.Any()0).ToList();

例子;

作者 1、2、3 没有书,然后在执行 Any() 时运行以下查询

SELECT AuthorId,BookId,BookName from Books Where AuthorId = 1

SELECT AuthorId,BookId,BookName from Books Where AuthorId = 2

SELECT AuthorId,BookId,BookName from Books Where AuthorId = 3

现在这是怎么发生的!!

最佳答案

在这种情况下,我建议使用子查询 而不是JOIN。原因是一旦我们需要切换查询以找出 Authors have some books,JOIN 将乘以结果集(Authors with 2 books 将被列出两次等)

此外,让我们将 NHibernate 本地 Linq 提供程序语法与 Query 一起使用扩展名(需要返回 IQueryable<> ) 实现这一点的语法是:

子选择:

var subquery = session.Query<Book>()
    .Select(b => b.Author.AuthorId)
    ;

没有任何书籍的作者集合

var list = session.Query<Author>()
    .Where(a => !subquery.Contains(a.AuthorId))
    ;

如果我们想要获得拥有一些书籍的作者列表,我们只需删除 NOT 运算符 (!) 并应用分页(Take()Skip()),这将返回正确的结果,而不是相乘的结果。

关于c# - NHibernate to Linq 获取没有出过书的作者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19731894/

相关文章:

c# - VS2008 下的 dmbl 设计器文件有问题?

sql - 由于 case 语句,同一 ID 的多个实例填充在不同的列中

sql - 如何在 sql 查询中插入计数列

c# - LINQ where 子句中的可变条件

c# - linq 按对象分组

c# - Microsoft Graph .NET SDK - 检索 ListItem 字段

c# - 使用 .Save() 时,状态文档中的 token EndDocument 将导致无效的 XML 文档

c# - 匹配文本模板中的多个字符串

Java SQL 插入多个变量

c# - 如果没有匹配项,则获取第一个单个匹配元素或第一个?