如何将SQL的EXCEPT“转换”为(N)Hibernate(Criteria API)?

时间:2012-03-29 21:09:00

标签: c# hibernate nhibernate criteria-api nhibernate-criteria

我正在处理一个案例,我通常在SQL中应该有一个'except'关键字。 此时我没有找到在NHibernate中完成此任务的解决方案。

这是一个有两个表的解决方案:用户表和FK表(包括用于在NH中轻松工作的PK)。 下面的SQL的含义是为某个用户尚未标记的用户提供记录。 所以,如果我们有3个用户:John,Jane en Jelain。 如果John没有标记任何人:给jane和jelain回复 如果John标记Jane:给Jelain回馈 如果约翰标记了简和杰兰:什么都不给。

用于获取尚未标记的用户的SQL:

SELECT Id, DisplayName, Date, ProfilePicUrl
FROM MyDB.dbo.Users u
EXCEPT
SELECT u.Id, Displayname, Date, ProfilePicUrl
FROM MyDB.dbo.Users u
FULL OUTER JOIN MyDB.dbo.TaggedUsers t
ON u.Id=t.TargetId
WHERE
t.ShooterId = '1234' OR
u.Id = '1234'

3 个答案:

答案 0 :(得分:2)

我认为ICritearia没有例外,但您可以使用“Not IN”:

session.QueryOver(T).WhereRestrictionOn(t => t.SomeProperty).Not.IsIn(object[])

我认为它是一样的,看看:

http://blog.sqlauthority.com/2007/05/22/sql-server-2005-comparison-except-operator-vs-not-in/

答案 1 :(得分:1)

好吧 - 我想你可以使用外连接将你的语句翻译成一个语句:

select id, DisplayName, Date, ProfilePicUrl
from MyDB.dbo.Users u 
right outer join MyDB.dbo.TaggedUsers t on u.id = t.targetId
where t.ShooterId = '1234' or u.ID <> '1234' and t.ShooterId is null

这可以转换为标准声明 - 但我必须知道你的映射能够做到这一点

.CreateAlias("TaggedUsers", "t", NHibernate.SqlCommand.JoinType.LeftOuterJoin)
.Add(Restrictions.IsNull("t.ShooterId")
.Add(Restrictions.Not(Restrictions.Eq("ID));

在没有测试的情况下创建它总是很难 - 但我希望你能得到我的想法。

修改

好吧 - 它看起来应该是左外连接 - 而不是右外连接

答案 2 :(得分:0)

我一直在检查Anton和Bernhardrusch的两个答案并试一试。

当读一个答案时,我认为可以用左外连接重写我的查询,并用NOT IN过滤掉记录。

这让我想到了这段代码:

SELECT *
FROM MyDB.dbo.Users u 
LEFT OUTER JOIN MyDB.dbo.TaggedUsers t ON u.Id=t.TargetId
WHERE t.ShooterId <> '6A17DC45-AB54-4534-B13B-A02001347664' 
  AND u.Id <> '6A17DC45-AB54-4534-B13B-A02001347664'
   OR t.ShooterId is null

使用Criteria API进行翻译,但遗憾的是,此代码在使用多个用户时无效

此时我决定用代码而不是SQL 来解决这个问题。

所以我会做两个查询(选择所有用户并选择所有标记用户对应的用户ID),并附上.future并过滤掉后者的第一个。

如果有人知道更好的解决方案。请告诉我。

也许除了以后进入NHibernate。我们会看到。我现在就给出自己的答案作为这个问题的答案。