NHibernate:使用SetProjection返回一个没有延迟加载的引用属性

时间:2011-01-21 01:21:04

标签: nhibernate

我映射了以下两个类:

public class Foo
{
    public virtual Guid Id { get; set; }
    public virtual Bar Bar { get; set; }
}
public class Bar
{
    public virtual Guid Id { get; set; }
    public virtual string Name { get; set; }
}

我有以下标准:

return Session.CreateCriteria<Foo>("f")
    .CreateAlias("f.Bar", "b")
    .SetProjection(Projections.Property("f.Bar"))
    .List<Bar>();

这将生成以下SQL:

select b.Id from Foo f
inner join Bar on f.BarId = b.Id

注意如何仅返回Bar的ID,而不是整个类。我如何获得Bar的所有列?

3 个答案:

答案 0 :(得分:2)

解决方案取决于您的需求。

首先如果你需要返回实体栏,那么你的初始标准必须是Bar 类型,所以你只需:

session.CreateCriteria<Bar>().
       .List<Bar();

如果你需要添加一些基于Foo的限制,那么有两种方法。

  1. 使用HQL

    session.CreateQuery(

        "select b " +
        "from Foo f " +
        "inner join f.Bar b " +
        "where f.Id = 9 ")
    .List();
    
  2. 使用仅查询属性。通过在Bar映射文件中添加access =“noop”来完成此操作。

    <many-to-one name="foo" access="noop" class="Foo" column="FooFk"/>

  3. 请注意,您的域模型不必更改!您不需要在Bar类中添加“foo”属性/字段。 现在,您可以在查询中使用该属性,如:

    session.CreateCriteria<Bar>()
        .CreateAlias("foo", "f")
        .Add(Restrictions.Eq("f.Id", 9))
        .List<Bar>();
    

答案 1 :(得分:0)

如果不符合单一条件,请使用DetachedCriteria

var subquery = DetachedCriteria.For<Foo>("f")
    .SetProjection(Projections.Property("f.Bar"))
    // more filter criteria ...

return session.CreateCriteria<Bar>
    .SetProjection(Subqueries.PropertyIn("id", subquery));

创建如下的sql:

select Bar.*
from Bar
where Bar.id in (Select b.id from Foo f inner join Bar b on ...)

如果你在子查询中有一些基于Foo的过滤条件,那么显然才有意义。

答案 2 :(得分:0)

如果上面的分离标准查询不能解决这个问题,那么应该是一个简单的HQL查询。

var hqlQuery="select b from Foo as f inner join f.Bar as b";

现在运行此查询,如下所示:

Session.CreateQuery(hqlQuery).List<Boo>();

如果需要,您现在也可以在查询中添加条件。

希望这会有所帮助..我可以告诉你如何使用Criteria做到这一点,但我认为这对你来说更容易,因为你似乎对SQL感到满意。