1

I have items. Each item belongs to a group. And each item owns a (possibly empty) list of tags (strings) useful for boosting text search. The search should find items matching their description, description of the group they belong to or one or more tags (all in OR conditions).

I'm trying to select items by a search key through the following QueryOver.

Item i = null;
ItemGroup g = null;
String tag = null;

session
    .QueryOver<Item>(() => i)
    .JoinAlias(x => x.Group, () => g, JoinType.InnerJoin)
    .JoinAlias(x => x.Tags, () => tag, JoinType.LeftOuterJoin) //left outher join because it is possible for an item to have no tags at all.
    .Where(
        new Disjunction()
            .Add(Restrictions.On(() => p.Description).IsInsensitiveLike(searchKey, MatchMode.Anywhere))
            .Add(Restrictions.On(() => g.Description).IsInsensitiveLike(searchKey, MatchMode.Start))
            .Add(Restrictions.On(() => tag).IsInsensitiveLike(searchKey, MatchMode.Start)) //this condition throws an exception
    )
    .Take(maxResults)
    .Future();

Item class is mapped as follows:

<class name="Item" table="Items">
<id name="Id">
    <generator class="guid.comb" />
</id>

    <natural-id>
        <property name="Code" not-null="true" />
    </natural-id>
    <property name="Description" not-null="true" />
    <many-to-one name="Group" column="ID_Group" not-null="true" fetch="join" />
    <property name="ExpiryDate" />
    <list name="Tags" table="Items_Tags">
        <key column="ID_Item" />
        <index column="Idx" />
        <element column="Tag" />
    </list>
</class>

Query execution throws a NullReferenceException. Removing the last condition in the disjunction the exception is not thrown.

I didn't get rid of this without using magic strings.

4

2 回答 2

1

使用这个,如果我误解了请纠正我

session
    .QueryOver<Item>(() => i)
    .JoinAlias(x => x.Group, () => g, JoinType.InnerJoin)
    .JoinAlias(x => x.Tags, () => tag, JoinType.LeftOuterJoin) //left outher join because it is possible for an item to have no tags at all.
    .Where(
        new Disjunction()
            .Add(Restrictions.On(() => p.Description).IsInsensitiveLike(searchKey, MatchMode.Anywhere))
            .Add(Restrictions.On(() => g.Description).IsInsensitiveLike(searchKey, MatchMode.Start))
            .Add(Restrictions.On(() => tag.Tag).IsInsensitiveLike(searchKey, MatchMode.Start)) //this condition throws an exception
    )
    .Take(maxResults)
    .Future();
于 2012-08-31T07:34:47.383 回答
1

我最近没有检查过,但据我所知 NHibernate 不支持直接使用 QueryOver 或 Criteria API 查询值集合。

我建议您最好的解决方法是使用 SQLCriteria:

        var tagCriteria = new SQLCriterion(
            new SqlString("{alias}.Id IN (SELECT ID_Item FROM Items_Tags WHERE Tag LIKE ?)"),
            new[] {searchKey + "%"},
            new[] {NHibernateUtil.String}
            );

        session
            .QueryOver<Item>(() => i)
            .JoinAlias(x => x.Group, () => g, JoinType.InnerJoin)
            .Where(
                new Disjunction()
                    .Add(Restrictions.On(() => p.Description).IsInsensitiveLike(searchKey, MatchMode.Anywhere))
                    .Add(Restrictions.On(() => g.Description).IsInsensitiveLike(searchKey, MatchMode.Start))
                    .Add(tagCriteria)
            )
            .Take(maxResults)
            .Future();
于 2012-08-31T15:40:21.297 回答