如何使用nHibernate中的一个子集筛选项目
本文关键字:一个 子集 筛选 项目 nHibernate 何使用 | 更新日期: 2023-09-27 18:29:33
我有一个对象,看起来如下。。。
<?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();
我显然做错了什么。问题是,是否可以搜索数据对象的子集?还是对我来说,直接搜索子表然后找到其父表更好?
我想你差不多到了。
I。先映射的一些注意事项。。。
首先,我假设EmailClass
和Person
也有关系(因为在DB级别上这是双向关系)。
public class EmailClass
{
...
public virtual Person Person { get; set; } // inverse mapping
}
这是合乎逻辑的,因为这个DB关系无论如何都是存在的。它已经被表示为一个名为Email
的人的<set>
。而且应该也是必须的,因为我们使用了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
我想说,通常,我们可以看到,用作根实体(Person)的键的<id>
列名与用于集合映射的the <key>
列相同。
因此,我希望EmailClass
表应该像"ItemId"
或"Person_ID"
一样包含列,这将保留对Person
表的引用。
II。子查询过滤
现在让我们继续查询,希望以上情况成立。
// 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();
所以,正如我们所看到的,几乎在那里。。。LIKE的QueryOver ish样式,以及基本的WHERE子句Person=EmailAddress.Person
III。映射。。。建议
请让我也提供一些我期望/建议的地图草案:
public class Person
{
public virtual int ItemId { get; set;}
public virtual IList<EmailClass> Emails { get; set; } // plural Emails
}
public class EmailClass
{
...
public virtual Person Person { get; set; } // inverse mapping
}
映射:
<class name="Person" ...
...
<set name="Emails" // plural
cascade="all-delete-orphan" // usually makes sense to rely on NHibernate cascade
batch-size="25" // great feature improving 1 + N issue
inverse="true" > // already used, improves WRITE operations sequence
<key column="ItemId" /> // ItemId should column in the EmailClass table
<one-to-many class="EmailClass" />
</set>
</class>
<class name="EmailClass">
<id ...
<many-to-one name="Person" column="ItemId" /> // the same column as in above <set
...
您可能想要:
session.QueryOver<Person>()
.JoinQueryOver(p => p.EmailClass)
.Where(e => e.EmailAddress.IsLike(strSearch, MatchMode.Anywhere))
.Future<Person>();
这假定EmailClass.EmailAddress
是string
。
这将生成如下所示的SQL:
select
Person.* /* all person fields */
from
Person
inner join EmailClass on EmailClass.Name = Person.Name
where
EmailClass.EmailAddress like '%strSearch%' /* your search term */