我对NHibernate的世界相当陌生,我似乎无法得到这个使用条件查询的工作:查询多对多关系或查询实体上的集合(集合/包) 。我搜索了互联网并检查了我们所有的NHibernate书籍,但我无法找到针对“挑战”的具体答案。查询多对多集合或如何在条件查询中包含多对多表格?
我已经做了一个简化的例子,我试图解决的问题。我有一张带书籍的桌子,一张带有类别的桌子和一本包含每本书类别的多对多桌子。下面是一些技术性的:
数据结构:
create table tableBook
(
BkId integer not null default autoincrement,
BkTitle char(40) not null,
BkWriter char(40) not null,
primary key (BkId)
);
create table tableCategory
(
CatId integer not null default autoincrement,
CatCode char(3) not null,
CatDesc char(40),
primary key (CatId)
);
create table tableCategoriesPerBook
(
CpbId integer not null default autoincrement,
CpbBkId integer not null, /*foreign key to tableBook*/
CpbCatId integer not null, /*foreign key to tableCategory*/
primary key (CpbId)
);
alter table tableCategoriesPerBook add foreign key FK_CpbBkId (CpbBkId) references tableBook (BkId) on update Restrict on delete Cascade;
alter table tableCategoriesPerBook add foreign key FK_CpbCatId (CpbCatId) references tableCategory (CatId) on update Restrict on delete Cascade;
create unique index idx_CpbCatId_CpbBkId on tableCategoriesPerBook (CpbCatId, CpbBkId);
C#类:
public class BookEntity
{
public virtual Int32 BookId { get; set; }
public virtual string BookTitle { get; set; }
public virtual string BookWriter { get; set; }
private readonly IEnumerable<CategoryEntity> _categories = new ObservableCollection<CategoryEntity>();
public virtual IEnumerable<CategoryEntity> Categories
{
get { return _categories; }
}
}
public class CategoryEntity
{
public virtual Int32 CategoryId { get; set; }
public virtual string CategoryCode { get; set; }
public virtual string CategoryDesc { get; set; }
}
NHibernate的映射:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping namespace="Domain" assembly="Domain" xmlns="urn:nhibernate-mapping-2.2">
<class name="Domain.BookEntity" table="tableBook">
<id name="BookId" column="BkId" type="Int32">
<generator class="native" />
</id>
<property name="BookTitle" column="BkTitle" type="string" length="40"/>
<property name="BookWriter" column="BkWriter" type="string" length="40"/>
<idbag name="_categories" access="field" table="tableCategoriesPerBook">
<collection-id type="Int32" column="CpbId">
<generator class="native"/>
</collection-id>
<key column="CpbBkId" property-ref="BkId"/>
<many-to-many column="CpbCatId" class="Domain.CategoryEntity, Domain" />
</idbag>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping namespace="Domain" assembly="Domain" xmlns="urn:nhibernate-mapping-2.2">
<class name="Domain.CategoryEntity" table="tableCategory">
<id name="CategoryId" column="CatId" type="Int32">
<generator class="native" />
</id>
<property name="CategoryCode" column="CatCode" type="string" length="3" />
<property name="CategoryDesc" column="CatDesc" type="string" length="40" />
</class>
</hibernate-mapping>
我的问题:是否有可能查询(使用ICriteria和/或分离标准)数据库,以便我得到其中的一本书我指定的类别(例如:在catA或catB中,也可以是“和”)?我想在查询中优化它,而不是在C#中(因为我需要从数据库中读取所有书籍,然后才能根据它们的标签集合过滤对象)。如果我手工编写的SQL,我会产生这样的:
SELECT * FROM tableBook
WHERE EXISTS
(
SELECT 1
FROM tableCategoriesPerBook
INNER JOIN tableCategory on (CpbCatId = CatId and CpbBkId = BkId)
WHERE CatCode in ('001', '002')
)
因为我没有为tableCategoriesPerBook实体,我不明白的方式来获得该表与标准查询。我宁可不使用添加一些手写的一张SQL表达式:
criteria.Add(Expression.Sql("exists(.....)");
最后一个重要的因素:我使用的是棕地数据库,所以我不能改变结构!这是我必须用数据库方式进行工作。
嗨Yads,非常感谢你的帮助。我看了很多其他的stackoverflow帖子,但没有让我更接近解决这个问题。你的代码示例几乎为我做了! '.Add(Restrictions.Eq(“bookCat.BookId”,“book.BookId”))是不正确的,但这对我来说很容易解决,我用下面的代码替换它:'.Add(Property.ForName(“ bookCat.BookId“)。EqProperty(”book.BookId“))'。非常感谢您的帮助。 – TedOnTheNet 2011-03-22 15:31:07