I would like to know if there is a way to create a Restriction on a primitive collection of a Model in NHibernate.3.3.3?

Here's the details:

class Parent { 
    IEnumerable<string> ChildNames { get; set; }

}

I need to search like so:

private DetachedCriteria BuildQuery() {
    var inNames = { "Bob", "Sam", "Dan" };
    var query = DetachedCriteria.For<Parent>("parent");
    query.Add(Restrictions.In("ChildNames", inNames));
    return query;
}

I found this old question that says it's not possible, but given the fact that it's old and doesn't have a ton of upvotes, I'd like to confirm before I refactor.

If I can do it and I'm totally botching it, I'll take that help as well!

有帮助吗?

解决方案 2

I ended up, like many, refactoring the collection into a strong type.

其他提示

In this scenario, we can use Projection (something less type-safe, then mapped Property, but more flexible).

Let's expect the mapping like this:

<bag name="ChildNames" inverse="false" lazy="true" table="[dbo].[ChildNames]" 
    cascade="all"
    batch-size="25">
  <key column="ParentId" />
  <element type="System.String" column="ChildName" />
</bag>

Then we can adjust the Build query method like this:

protected virtual DetachedCriteria BuildQuery()
{
    var inNames = new [] { "Bob", "Sam", "Dan" };

    // parent query reference
    var query = DetachedCriteria.For<Parent>("parent");
    // reference to child query
    var child = query.CreateCriteria("ChildNames");

    // let's project the column name of the Element, e.g. 'Name'
    var columnNameProjection = Projections.SqlProjection(
        "ChildName as name", null, new IType[] { NHibernateUtil.String }
        );

    // in clause
    child.Add(Restrictions.In(
        columnNameProjection, inNames
        ));

    return query;
}

And this is what we will get:

SELECT ...
 FROM Parent this_ 
  inner join [dbo].[ChildNames] childNames3_ 
    on this_.ParentId=childNames3_.ParentId 
 WHERE ChildName in (@p0, @p1, @p2)
 ...
 @p0=N'Bob',@p1=N'Sam',@p2=N'Dan'

The caveat:

While this is in deed working... the ChildName is used without the Alias. That could be pretty tricky to fulfill... so be careful, if there are more columns with the name ChildName in this scenario

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top