如何在NHibernate 3中实现搜索查询(使用NHibernate.Linq)

时间:2011-05-31 22:53:33

标签: join lazy-loading linq-to-nhibernate queryover

我正在尝试使用NHibernate构建一个搜索查询,它将过滤来自几个不同表的参数,并产生一些合理的SQL,可以利用NHibernate的延迟加载。 Fromm在线阅读各种提示,似乎最新和最好的方法是使用QueryOver对象有条件地添加正在使用的参数,如下面的代码片段所示:

Hibernate.Criterion.QueryOver<Models.Site, Models.Site> query = NHibernate.Criterion.QueryOver.Of<Models.Site>();

if (!string.IsNullOrEmpty(state))
                query = query.WhereRestrictionOn(r => r.State.StateName).IsInsensitiveLike("%" + state + "%");

if (startDate.HasValue)
                    query = query.Where(r => r.Events
                                            .Where(e=>e.EventDate >= startDate.Value)
                                            .Count() > 0
                                    );

return query.GetExecutableQueryOver(currentSession).Cacheable().List();

(一个事件有一个外键到站点)

我有两个问题: 如何过滤子对象而不仅仅是父对象?上面的示例代码为我提供了匹配事件的所有站点,但在该站点内,我只想要匹配的事件。如果我应该使用连接或子查询,怎么样?我很困惑通过连接或子查询来保持我的树状层次结构与延迟加载。

编辑:已经回答了这个问题。谢谢psousa! 如何添加or子句?我发现了对Disjunction对象的引用,但看起来似乎没有使用QueryOver方法。

编辑: 我想得到一个按站点标准过滤的站点列表(顶级对象),每个站点都应该有按事件标准过滤的事件列表。

我希望它能像以下那样生成SQL:

SELECT *
FROM [site] s
    LEFT JOIN [event] e ON s.siteID = e.siteID
WHERE e.eventDate > @eventDate
    AND (s.stateCd = @state OR s.stateName LIKE @state)

2 个答案:

答案 0 :(得分:0)

我会这样做:

//use aliases. Optional but more practical IMHO 
Site siteAlias = null;
Event eventAlias = null;

//use JoinAlias instead of JoinQueryOver to keep the condition at the "Site" level
var results = Session.QueryOver(() => siteAlias)
        .JoinAlias(m => m.Event, () => eventAlias)
        .Where(() => eventAlias.EventDate > eventDate)
        .Where(() => siteAlias.StateCd == state || Restrictions.On(() => siteAlias.StateName).IsLike(state))
        .List();

您提到了Disjunction类,它实际上可能与QueryOver一起使用,例如:

var disjunction= new Disjunction();
disjunction.Add(() => siteAlias.StateCD == state);
disjunction.Add(Restrictions.On(() => siteAlias.StateName).IsLike(state));

QueryOver查询将是:

var results = Session.QueryOver(() => siteAlias)
        .JoinAlias(m => m.Event, () => eventAlias)
        .Where(() => eventAlias.EventDate > eventDate)
        .Where(disjunction)
        .List();

答案 1 :(得分:0)

当使用psousa建议的连接别名时,您将获得对象结构和行结构的奇怪组合的结果,顶级对象由附加到它们的子对象复制。为了得到我想要的结果,你可以使用TransformUsing和DistinctRootEntityResultTransformer,如下面的代码所示:

    Site siteAlias = null;
    Event eventAlias = null;

    var results = currentSession.QueryOver<Site>(() => siteAlias)
            .JoinAlias(m => m.Event, () => eventAlias)
            .Where(() => eventAlias.EventDate > eventDate)
            .Where(() => siteAlias.StateCd == state || Restrictions.On(() => siteAlias.StateName).IsLike(state))
            .TransformUsing(new NHibernate.Transform.DistinctRootEntityResultTransformer())
            .List();