12

如何使用 CreateCriteria 编写以下 SQL:

SELECT * FROM FooBar fb
WHERE EXISTS (SELECT FooBarId FROM Baz b WHERE b.FooBarId = fb.Id)
4

3 回答 3

28

您可以这样做:

var fooBars = Session.CreateCriteria<FooBar>()
        .Add(Restrictions.IsNotEmpty("Bazs")).List<FooBar>();

...假设 FooBar 对象中有一个集合属性(一对多)“Bazs”。

或者,您可以使用这样的分离标准:

DetachedCriteria dCriteria = DetachedCriteria.For<Baz>("baz")
        .SetProjection(Projections.Property("baz.FooBarId"))
        .Add(Restrictions.EqProperty("baz.FooBarId", "fooBar.Id"));

var fooBars = Session.CreateCriteria<FooBar>("fooBar")
        .Add(Subqueries.Exists(dCriteria)).List<FooBar>();
于 2009-11-18T00:45:30.697 回答
5

刚刚解决了一个相关问题并最终找到了一个解决方案,我想我会在这里分享答案:

假设您想要原始问题查询,并在子查询上附加一个条件:

SELECT * FROM FooBar fb
WHERE EXISTS (SELECT FooBarId FROM Baz b WHERE b.FooBarId = fb.Id
              AND Quantity = 5)

假设您在 Baz 类上有一个对父级的引用,称为 FooBarRef [在 Fluent Map 类中您将使用 References() 方法],您将按如下方式创建查询:

DetachedCriteria dCriteria = DetachedCriteria.For<Baz>("baz")
        .SetProjection(Projections.Property("baz.FooBarId"))
        .Add(Expression.EqProperty("this.FooBarId", "FooBarRef.Id"))
        .Add(Expression.Eq("baz.Quantity", 5));

var fooBars = Session.CreateCriteria<FooBar>("fooBar")
        .Add(Subqueries.Exists(dCriteria)).List<FooBar>();

我不是 100% 相信别名“this”的硬编码,这是 NHibernate 自动分配给查询中的根实体(表)的别名,但这是我发现引用键的唯一方法子查询中的父查询表。

于 2010-07-30T07:06:42.133 回答
3

我想出了如何使用 IsNotEmpty 表达式来做到这一点。这里它使用 NHibernate Lambda 扩展:

Session.CreateCriteria<FooBar>()
    .Add(SqlExpression.IsNotEmpty<FooBar>(x => x.Bazes))
    .List<FooBar>();
于 2009-11-18T00:50:19.957 回答