将 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
所以,尝试从简单的东西开始,一旦成功,即使是复杂的东西也会。
请您告诉我如何使用 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
所以,尝试从简单的东西开始,一旦成功,即使是复杂的东西也会。