I have a table mapped in Fluent NHibernate. This table must join to another table on an ID, but must also filter the joined values on that table against a set of constant values. Consider the following SQL:
SELECT *
FROM
Table1
INNER JOIN
Table2 ON
Table1.Table2Id = Table2.Id
AND Table2.Category = 'A constant expression'
AND Table2.Language = 'A constant expression'
My fluent mapping for Table1 currently looks like this:
References(a => a.Table2).Nullable().Columns("Table2Id").ReadOnly();
How can I implement the constant expressions?
It sounds like you could use filters to do this.
First, you need to define the filter types
EDITED: As per comments, there is no
.ApplyFilter<TFilter>()
onReferences()
, so have updated with what I believe is the way to do it with filtersThe filters need to be applied in the fluent mappings
Finally, when you open a session, you need to enable the filters
If you're using an implementation of
ICurrentSessionContext
and the filters should always apply then you can enable the filters in the session returned from the call toICurrentSessionContext.CurrentSession()
.Now, when querying
Table1
, in order to activate the filters forTable2
, you need to indicate to NHibernate to join to the referencedTable2
; you can do this usingFetch(t => t.Table2).Eager
JoinQueryOver(t => t.Table2)
(and similar join strategies)Without indicating to NHibernate to make the join, the reference will be lazily-loaded by default and hence the filters will not be applied in the query. The downside is that
Table2
will be eager fetched but I don't know of a way to have the filters applied otherwise. The following queryresults in SQL similar to
which is akin to the SQL that you have in your question.
You might want have a look into
Formula(string formula)
where you could provide plain SQL. If it is a good idea to filter data on the mapping level is another question IMHO... As an example have a look here.I have noticed that your mapping specifies Nullable and no eager fetching (by default it will be lazy loaded). So if you did want to generate the sql you have shown in your comment, you would not be able to do it with a simple
session.Get<Table1>()
. Even if you changed the mapping so that it was like this :You would most likely end up with a left outer join in the outputted sql. The only way you would be able to force a fetch with inner join (without downloading any extra NHibernate addons) would be to use a
session.QueryOver
(you may also be able to do this with session.Query and the NHibernate linq extensions). If this is the case, then you may as well specify your set of constants inside the QueryOver query.I think the ApplyFilter method shown by Russ does make the model retrieval much simpler, and its really good for code re-usability (if you have other tables with categories and languages), but since your table reference is a nullable reference, you have to use a query anyway. Maybe a combination of QueryOver with the filter would be the best (assuming you can get the later version of fluent NHibernate)