NHibernate Collection Sub Query

2019-02-25 18:38发布

问题:

Is there a way to add criteria to a mapping for NHibernate?

public class Course {
   public IList<Participant> Participants { get; set; }
   public IList<Participant> ActiveParticipants { get; set; }
}

The second property, ActiveParticipants should be a list of participants where their "Status" is set to "Active". Otherwise, is there a way to post process the class, but still maintaining Lazy Loading, as sometimes the "ActiveParticipants" property will not be used.

The reason it needs to be like this instead of using LINQ, is the class is injected into a dynamic "Mustache" template, which only works with standard properties. There are also several similar properties like this.

回答1:

If you have subclasses of Participant with the status being the DiscriminatorValue, I think you can have them as separate lists since this way nHibernate knows how to differentiate them.

public class ParticipantMap : ClassMap<Participant>
{
    public ParticipantMap()
    {
        DiscriminateSubClassesOnColumn("Status");
    }
}
public class ActiveParticipantMap : SubclassMap<ActiveParticipant>
{
    public ActiveParticipantMap ()
    {
        DiscriminatorValue("Active");
    }
}
// other subclasses of participant e.g. NonActive, etc.

public class Course {
    public IList<Participant> Participants {get;set;}
    public IList<ActiveParticipant> ActiveParticipants {get;set;}
    // any other lists of participant subclasses that you may have
}


回答2:

It seems, that in this case, we would need "dynamic" filtering. The mapped collection will sometimes contain contain all records, sometimes just those which meet some filtering criteria.

Exactly for this, we have:

18.1. NHibernate filters

NHibernate adds the ability to pre-define filter criteria and attach those filters at both a class and a collection level. A filter criteria is the ability to define a restriction clause very similiar to the existing "where" attribute available on the class and various collection elements. Except these filter conditions can be parameterized. The application can then make the decision at runtime whether given filters should be enabled and what their parameter values should be. Filters can be used like database views, but parameterized inside the application.

In order to use filters, they must first be defined and then attached to the appropriate mapping elements. To define a filter, use the element within a element:

<filter-def name="myFilter">
    <filter-param name="myFilterParam" type="String"/>
</filter-def>

Then, this filter can be attached to a class:

<class name="MyClass" ...>
    ...
    <filter name="myFilter" condition=":myFilterParam = MY_FILTERED_COLUMN"/>
</class>

or, to a collection:

<set ...>
    <filter name="myFilter" condition=":myFilterParam = MY_FILTERED_COLUMN"/>
</set>

Check more details here (xml)

  • Is it possible to use NHibernate Filters to filter through references?
  • NHibernate load entity with part of sub collection

(fluent mapping)

  • Limit collection to retrieve only recent entries for readonly entity


回答3:

You dont need a subquery to load a collection with additional condition.

HasMany(x => x.ActiveParticipants).Where("Status = 'Active'");