【问题标题】:Limit child entities without limiting parent entities - NHibernate限制子实体而不限制父实体 - NHibernate
【发布时间】:2012-11-25 17:37:36
【问题描述】:

我正在尝试限制映射集合的结果集。

这是一个简单的模型:

public class Table1 {
    public virtual long Id { get; set; }
    public virtual IList<Table2> Table2s { get; set; }
}


public class Table2 {
    public virtual long Id { get; set; }
    public virtual long Table1Id { get; set; }
    public virtual Table1 Table1 { get; set; }
    public virtual string Field { get; set; }
}

public class Table1Map : ClassMap<Table1> {
    public Table1Map () {
        Table("Table1");
        Id(x => x.Id).Column("Id").Not.Nullable().CustomType("Int64").GeneratedBy.Native();
        HasMany<Table2>(x => x.Table2s).Inverse().Not.LazyLoad().KeyColumns.Add("Table1Id").Fetch.Join();
    }
}

public class Table2Map : ClassMap<Table2> {
    public Table2Map () {
        Table("Table2");
        Id(x => x.Id).Column("Id").Not.Nullable().CustomType("Int64").GeneratedBy.Native();
        Map(x => x.Table1Id).Column("Table1Id").Not.Nullable().CustomType("Int64");
        Map(x => x.Field).Column("Field").Not.Nullable().CustomType("AnsiString").Length(25);
        References<Table1>(x => x.Table1, "Table1Id").Cascade.None();
    }
}

我想选择所有Table1s。我也想选择所有满足一定条件的Table2s(Table2.Field = 'value'),但是我不想限制我的Table1s,所以如果不满足条件就选择空Table2s .如果我想在 SQL 中执行此操作,我会执行以下操作:

SELECT *
FROM 
Table1
LEFT OUTER JOIN Table2 ON Table1.Id = Table2.Table1Id
WHERE
Table2.Field = 'value' or Table2.Field IS NULL

我应该如何构建我的 NHibernate 查询以达到预期的结果?我想要Table1s 的列表,并且在每个Table1 中我想要Table2s 的空列表(因为没有Table2s 符合条件),或者Table2 的列表符合标准的。

我正在尝试类似以下的方法,但这显然行不通:

List<Table1> result = new List<Table1>();
IQueryable<Table1> query = session.Query<Table1>();
if (value != null) {
    query = query.Where(x => x.Table2s.Field == value);
}
query = query.OrderBy(x => x.Id);
result = query.ToList();

【问题讨论】:

    标签: c# .net nhibernate left-join fluent


    【解决方案1】:

    我认为这是不可能的。 Hibernate 加载完整的实体及其所有属性(如果没有激活延迟​​加载)。 如果你保存了这样一个类型为 table1 的已加载实体而没有所有 table2,hibernate 应该做什么?

    您应该创建某种视图对象 (dvo),其中包含 table1 的相关部分和符合条件的 table2 子项列表。选择可以由projection完成。

    【讨论】:

      【解决方案2】:

      有很好的文档 - 16.4。协会

      http://nhibernate.info/doc/nh/en/index.html#queryqueryover-associations

      QueryOver 语法如下所示

      IQueryOver<Table1, Table2> myQuery = 
        session.QueryOver<Table1>()
         .Left.JoinQueryOver<Table2>(t => t.Table2s)
           .Where(
             Restrictions.Or(
               Restrictions.On<Table2>((t2) => t2.ID).IsNull, 
               Restrictions.On<Table2>((t2) => t2.Field).IsLike("value")
               )
             );
      var list = myQuery.List<Table1>();
      

      然后list 将返回满足条件的所有组合的集合。 (可以添加以后的 order by 或 distinct 或其他 porjections...)

      【讨论】:

      • 这是一个很好的答案,但有些限制。如果Table1 不仅有Table2s 的集合,而且还有Table3s 的集合,您还想过滤它们会怎样。提供的方法仅适用于两个实体。有没有更通用的方法?有另一种方法吗?谢谢!
      • 是的! ;) NHibernate Criteria API 非常强大。您可以使用投影(选择一些属性,选择不同的...总和,平均)您可以加入任何方式...您可以在 WHERE 子句中过滤...任何东西。请查看文档 (nhforge.org/doc/nh/en/index.html#querycriteria) 或 Ayende 的博客
      • 你有一个有效的例子吗?我没有发现文档对我的示例特别有用。我尝试实施您上面的建议,暂时忽略“Table3”,但没有得到任何结果。如果您有一个使用强大的 Criteria API 和多个映射集合的工作示例,那将是一个很大的帮助!
      • 有一个起点,从哪里继续:完成查询后如我上面的回答,您可以继续添加新条件:myQuery.RootCriteria.CreateCriteria(...
      猜你喜欢
      • 1970-01-01
      • 2014-04-05
      • 1970-01-01
      • 1970-01-01
      • 2017-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-28
      相关资源
      最近更新 更多