如何使用nHibernate中设置的子项之一过滤项目

时间:2014-11-06 22:22:58

标签: c# nhibernate queryover

我有一个看起来如下的对象.​​.....

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping namespace="test" assembly="test" xmlns="urn:nhibernate-mapping-2.2">

<class name="Person" table="`Person`">
        <id name="ItemId" access="property" column="`ItemId`">
            <generator class="native" />
        </id>
        <property name="Name" column="`A`" />
        <property name="Age" column="`B`" />
        <set name="Email" inverse="true">
            <key column="`Name`" />
            <one-to-many class="EmailClass" />
        </set>
    </class>
</hibernate-mapping>

我想通过电子邮件地址

来执行nHibernate查询来过滤这些记录

我已经尝试过这些方法......

var childCriteria = QueryOver.Of<EmailClass>().Where(c => c.EmailAddress.ToString().IsLike("%" + strSearch + "%")).Select(c => c.EmailID);

var query = session.QueryOver<Person>().WithSubquery.WhereExists(childCriteria).Future();

我显然做错了什么。问题是,是否可以搜索数据对象的子集?或者直接搜索子表然后找到它的父项是否更好?

2 个答案:

答案 0 :(得分:1)

你可能想要:

session.QueryOver<Person>()
    .JoinQueryOver(p => p.EmailClass)
    .Where(e => e.EmailAddress.IsLike(strSearch, MatchMode.Anywhere))
    .Future<Person>();

这假设EmailClass.EmailAddressstring

这将生成如下所示的SQL:

select
    Person.* /* all person fields */
from
    Person
    inner join EmailClass on EmailClass.Name = Person.Name
where
    EmailClass.EmailAddress like '%strSearch%' /* your search term */

答案 1 :(得分:1)

我差不多到了,我说。

予。首先映射的一些注释...

首先,我假设EmailClassPerson以及有关系(因为在DB级别这是双向关系)

public class EmailClass 
{
    ...
    public virtual Person Person { get; set; } // inverse mapping
}

这是合乎逻辑的,因为无论如何这个DB关系是存在的。它已被表达为名为<set>的人Email。并且也应该是必须的,因为我们使用 inverse="true" ,这需要双向映射......

这也让我对映射提出质疑。您确定,这种映射是正确的:

<class name="Person" ...
    // KEY column of this entity is ItemId (seems to be int)
    <id name="ItemId" column="`ItemId`" ...
    ...
    <set name="Email" inverse="true">
        // this mapping says: NHibernate, try to find the value
        // of the ItemId in the Person table
        // in the column Name of the table EmailClass ... ?
        <key column="`Name`" />
        ...
        // would expect
        <key column="ItemId" /> // column inside of EmailClass table

我想说,通常,我们可以看到,用作根实体(人)的键的<id>列名称与{{1}相同用于集合映射的列。

因此,我希望the <key>表格应包含,例如EmailClass"ItemId",这样可以保留对{{1}的引用表格。

II。子查询过滤

现在让我们继续查询,期待以上情况属实。

"Person_ID"

所以,正如我们所看到的,几乎就是...... LIKE的一些 QueryOver-ish 样式,以及必要的WHERE子句Person = EmailAddress.Person

III。映射...建议

请允许我提供一些我期望/建议的映射草案:

Person

映射:

// An Alias, to be used later
Person person = null;

var childCriteria = QueryOver
    .Of<EmailClass>()
    // more QueryOver native style of a LIKE expression
    .WhereRestrictionOn(c => c.EmailAddress).IsLike(strSearch, MatchMode.Anywhere)
    // trick here
    // if we want to use the EXISTS later
    // we need to join outer and inner query here
    // and that's a place for outer query ALIAS
    .Where(c => c.PersonId == person.ItemId)
    .Select(c => c.PersonId); // must select something...

var query = session
    // ALIAS expressing the outer query in action again
    .QueryOver<Person>(() => person)
    .WithSubquery
    .WhereExists(childCriteria)
    .Future();