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

发布于 2024-11-10 11:25:28 字数 1316 浏览 10 评论 0原文

我正在尝试使用 NHibernate 构建一个搜索查询,它将过滤来自多个不同表的参数,并生成可以利用 NHibernate 延迟加载的有点合理的 SQL。 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();

事件有一个指向站点的外键)

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

编辑:这已得到回答。谢谢普苏萨! 如何添加 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)

I'm trying to build a search query using NHibernate that will filter on parameters from several different tables and result in somewhat-reasonable SQL that can take advantage of NHibernate's lazy-loading.
Fromm reading various tips online, it seems that the latest-and-greatest way to do that is to use the QueryOver object to conditionally add in the parameters being used, as in the following snippet:

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();

(an event has a foreign-key to site)

I have two questions:
How do I filter the child objects, instead of just the parent? The sample code above gives me all the sites with a matching events, but within that site, I only want matching events. If I'm supposed to use a join or a subquery, how? I'm confused about maintaining my tree-like hierarchy with lazy-loading through a join or subquery.

Edit: this has been answered. Thanks psousa!
How do I add an or clause? I found reference to a Disjunction object, but it doesn't seem like that's available using the QueryOver method.

Edit:
I want to result in a list of sites (top level object) filtered by the site criteria, and each site should have its list of events filtered by the event criteria.

I expect it to generate SQL like the following:

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

谈下烟灰 2024-11-17 11:25:28

我会这样执行该查询:

//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();

I would do that query as such:

//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();

You mentioned the Disjunction class, and it may in fact be used with QueryOver, like:

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

The QueryOver query would be:

var results = Session.QueryOver(() => siteAlias)
        .JoinAlias(m => m.Event, () => eventAlias)
        .Where(() => eventAlias.EventDate > eventDate)
        .Where(disjunction)
        .List();
演多会厌 2024-11-17 11:25:28

当使用 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();

When using a join alias as suggested by psousa, you will get results in a strange combination of an object structure and a row structure, with the top-level objects being duplicated by the child objects that are attached to them. In order to get the results I was looking for, you can use TransformUsing and a DistinctRootEntityResultTransformer as shown in the following code:

    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();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文