将 postgres 查询重写为 NHibernate

Rewriting postgres query to NHibernate

请您告诉我如何使用 NHibernate 的 QueryOver<>() Query<>() 或其他 NHibernate 方法编写以下内容,在切换数据库提供程序时不会涉及我重写此内容(以及许多其他类似查询)?

具有多个 table 连接的子查询让我很难翻译,因为我对 NHibernate 的了解有限。

return Session.CreateSQLQuery("select " +
                               "    boards.id, boards.name, boards.description, " +
                               "    (" +
                               "        select " +
                               "            count(topic.id) " +
                               "        from topic " +
                               "        left join users on users.id=topic.user " +
                               "        left join boards b on b.id=topic.bid " +
                               "        left join boards b2 on b2.id=b.bid " +
                               "        where (topic.bid=boards.id or b.bid = boards.id or b2.bid = boards.id) " +
                               "        and (b.type <= (:userType)) " +
                               "        and (b2.type is null or b2.type <= (:userType)) " +
                               "        and users.type > 0 " +
                               "        and users.chatban = 0" +
                               "    ) as TopicCount," +
                               "    (" +
                               "        select (max(posts.time) - max(read.time)) as t " +
                               "        from posts " +
                               "        left join users u on u.id=posts.user" +
                               "        left join topic on topic.id=posts.tid " +
                               "        left join read on read.topic=topic.id and read.userid=(:userId) " +
                               "        left join boards b on b.id=topic.bid" +
                               "        left join boards b2 on b2.id=b.bid" +
                               "        where " +
                               "            (topic.bid=boards.id or b.bid = boards.id or b2.bid = boards.id) " +
                               "            and (b.type <= (:userType)) " +
                               "            and (b2.type is null or b2.type <= (:userType)) " +
                               "            and not exists (select boardid from boardhigh where boardid=b.id and userid=(:userId))" +
                               "            and u.type > 0 " +
                               "            and u.chatban = 0 " +
                               "        group by topic.id " +
                               "        order by t desc " +
                               "        limit 1" +
                               "    ) as time " +
                               "from boards " +
                               "left join topic on topic.bid=boards.id " +
                               "where" +
                               "    boards.type <= (:userType) " +
                               (parentBoard.HasValue ? " and boards.bid = " + parentBoard.Value : "") +
                               "group by boards.id, boards.name, boards.description, boards.display " +
                               "order by boards.display desc, boards.name asc"
            )
            .SetInt32("userType", (int)UserHelper.LoggedInUser.UserType)
            .SetInt64("userId", UserHelper.LoggedInUser.Id)
            .List()
            .Cast<object[]>()
            .ToList()
            .Select(x => new BoardValueObject
            {
                Id = (int)x[0],
                Name = x[1].ToString(),
                Description = x[2].ToString(),
                TopicCount = (long)x[3],
                Time = x[4] as int?
            })
            .ToList();

谢谢

我非常怀疑您是否会收到 巨型 SQL 查询 及其转换的答案。同时,我想指出 approach/thinking 在使用 NHibernate 时的一些差异。

  • 首先使用实体​​。定义你的模型,业务领域模型 Users, Topics, Boards.
  • 花点时间了解延迟加载。很多数据可以通过简单的查询得到 User(s),然后导航到他的版块、主题...所有需要的数据都将加载到分隔的 SQL 语句中,但没有复杂的查询。
  • 请检查 batch-loading 的优势,这是一种如何避免 1+N SELECT 问题的技术。它确实运行良好,并且对已发布的 SQL 语句的数量产生了惊人的巨大影响。
  • 不要担心使用本机 SQL 来接收用户所需的“...”数据 (用诸如疯狂、令人难以置信、复杂的词替换点)。 NHibernate 首先是 ORM。它对与业务对象模型相关的所有 CRUD 操作都做得很好。支持任何 "SP like selects",但间接支持...通过 CreateSQLQuery

所以,尝试从简单的东西开始,一旦成功,即使是复杂的东西也会。