【问题标题】:NHibernate: Return a referenced property without lazy loading using SetProjectionNHibernate:使用 SetProjection 返回引用的属性而不延迟加载
【发布时间】:2011-01-21 01:21:04
【问题描述】:

我映射了以下两个类:

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 的所有列?

【问题讨论】:

  • 在您的代码示例中,您声明 .List(); ,但是您说只返回 Bar 的 Id。这是否意味着您会得到一个只有 Id 属性被水合的 Bar 列表?
  • 您可能需要考虑切换到 HQL,除非您有特定要求迫使您使用标准(动态搜索通常是最重要的)。

标签: nhibernate


【解决方案1】:

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

首先如果您需要返回实体 Bar,那么您的初始 Criteria 必须是 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" 来做到这一点。

    &lt;many-to-one name="foo" access="noop" class="Foo" column="FooFk"/&gt;

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

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

【讨论】:

    【解决方案2】:

    如果它不符合单个条件,请使用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 的过滤条件时才有意义。

    【讨论】:

      【解决方案3】:

      如果上面的分离条件查询在这里不起作用,那么这里应该是一个简单的 HQL 查询。

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

      现在按如下方式运行此查询:

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

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

      希望这会有所帮助。我可以告诉你如何使用 Criteria 来做,但我认为这对你来说更容易理解,因为你似乎对 SQL 很熟悉。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-05
        • 1970-01-01
        • 1970-01-01
        • 2012-09-14
        • 1970-01-01
        相关资源
        最近更新 更多