How to query a subproperty with NHibernate’s crite

2019-06-27 06:53发布

问题:

Assuming the following:

public class Order
{
   public virtual int OrderId {get;set}
   public virtual ISet<Product> Products {get;set}
}

public class Product
{
   public virtual int ProductId {get;set}
   public virtual string ProductName {get;set}
}

How would you query using the criteria api so that only an order with a specific orderid is returned and its Product collection should also be filtered down to Products whose Name start with the lettter P?

回答1:

I would go about this with a DetachedCriteria:

DetachedCriteria crit = DetachedCriteria.For<Order>();

crit.Add(Restrictions.Eq("OrderId",orderID);
crit.CreateCriteria("Products","products");
crit.Add(Restrictions.Like("products.ProductName","P%");

crit.List();

and then executing the criteria and getting the results.



回答2:

Simplest approach is to use an alias:

var productIdToSelect = 9;
var crit = Session.CreateCriteria(typeof(Order));
crit.CreateAlias("Product", "prod");
crit.Add(Expression.Eq("prod.Id", productIdToSelect));
var result = crit.List<Order>();


回答3:

I don't know the code you would have to write, but a point in the right direction:

http://www.nhforge.org/doc/nh/en/index.html#querycriteria-associations (14.4)

The key seems to be:

.SetResultTransformer(CriteriaUtil.AliasToEntityMap)

The documentation shows an example with cats and kittens.

Note that the kittens collections held by the Cat instances returned by the previous two queries are not pre-filtered by the criteria! If you wish to retrieve just the kittens that match the criteria, you must use SetResultTransformer(CriteriaUtil.AliasToEntityMap).



回答4:

Set up a filter on the mapping of the collection.

<filter name="letterFilter" condition="ProductName like ':letterSupplied'"/>

Then before running the Order query enable the filter

session.EnableFilter("letterFilter").SetParameter("letterSupplied", "P%");

then run the query

Order ord = session.CreateCriteria<Order>().Add(Restrictions.IdEq(suppliedId)).UniqueResult<Order>();

Note that the single quotes in the filter definition may not be required and also i place the % symbol with the supplied parameter as i don't know how NH would react a filter like

<filter name="letterFilter" condition="ProductName like ':letterSupplied%'"/>

or

<filter name="letterFilter" condition="ProductName like :letterSupplied%"/>