如何使用NHibernate检索List上的条件元素

时间:2010-06-28 17:35:25

标签: c# .net nhibernate

我正在使用NHibernate,我有两个映射我的DataBase架构的类:

public class A
{
    public virtual int Id { get; set;}
    public virtual List<B> MyList { get; set; }
}

public class B
{
    public virtual int Id { get; set; }
    public virtual DateTime Date { get; set; }
    public virtual A FKtoA { get; set; }
}

我想得到表A的所有条目,它们的MyList属性的所有元素的Date都小于给定值。

如何使用优雅的NHibernate语法来实现这一目标?

4 个答案:

答案 0 :(得分:1)

我欠你“优雅”部分......: - )

这是一个可能的HQL。请注意,颠倒了你的条件:我没有寻找“A具有其MyList属性的所有元素且日期小于给定值”,而是寻找“那个不要拥有MyList属性的任何元素,其中Date 大于或等于给定值“。

from A a
where a not in 
      (select a1
       from A a1, B b
       where b.Date >= :date
       and   b in elements(a1.MyList))

用法:

var results = session.CreateQuery("hql from above")
                     .SetParameter("date", DateTime.Today)
                     .List();

请注意,如果您在AB之间声明双向关系(通过添加A属性),则查询会更简单:

from A a
where a not in 
      (select b.A
       from B b
       where b.Date >= :date)

更新:以下是如何使用Criteria:

session.CreateCriteria<A>().Add(
    Subqueries.PropertyNotIn("id",
                             DetachedCriteria.For<A>()
                                 .CreateCriteria("MyList")
                                 .SetProjection(Projections.Property("id"))
                                 .Add(Restrictions.Ge("Date", DateTime.Today))))

答案 1 :(得分:0)

使用此

ICriteria criteria =  session.CreateCriteria<ClassOfTableOne>();
criteria.CreateAlias("FieldNameOfTypeTable2","aliasName");
criteria.SetFetchMode("aliasName", FetchMode.Join);
criteria.Add(Restrictions.Lt("aliasName.Date", yourdate));

答案 2 :(得分:0)

如果您的B类看起来像这样(A的MyList属性查找此FK)

public class B
{
    public virtual int Id { get; set; }
    public virtual DateTime Date { get; set; }
    public virtual A FK_ToA { get; set; }
}

然后我认为你正在寻找(HQL)

nhSes.CreateQuery("select b.FK_ToA from B b where b.Date < :passedDate")
     .SetTimestamp("passedDate", DateTime.Now).List<A>()

答案 3 :(得分:-1)

当前接受的答案依赖于相关的子查询,根据经验,该查询只是“错误的SQL”。

使用基于集合的语义而不是更具功能性的方法来表达这一点要好得多。

基本上你希望你的SQL看起来像这样:

SELECT
 A.Id
FROM A
 LEFT OUTER JOIN B ON A.Id = B.FKtoA
WHERE B.Date < @MyDate

这读作“我希望A中的一组列与一组B相关,其中B的日期小于某个值”。这可以使用ICriteria API实现:

ICriteria criteria =  session.CreateCriteria<A>();
criteria.CreateAlias("MyList", "b", JoinType.LeftOuterJoin)
criteria.Add(Restrictions.Lt("b.Date", myDate));
criteria.SetResultTransformer(new DistinctRootEntityResultTransformer());
criteria.List<A>();

部分技巧是使用NHibernate的内置DistinctRootEntityResultTransformer:由于左外连接可以返回每个B的多个A实例,我们希望我们的ICriteria只返回不同的实例(假设我们不关心订购或其他什么其他人)。