Isn't it a bit strange with filters on many-to-one relationships? I know this comment might be a bit late but I'm still on 2.0 in live projects and haven't really given it any deeper thought until now.
Let's say you have a User entity. Other entities might have CreatedBy and/or UpdatedBy prop. When an User is unactivated a flag is set. NH:s filters have been perfect in this situation. If persons are queried for, unactive ones won't be returned - perfect. However if you want to know who created a certain entity you can (could?) always look at the prop and the unactive User is still there.
If I've understood it correctly, many-to-one now starts taking filters into consideration, the above will work only if the query in the first place was written in a certain way. Feels a bit strange to me.
Also, as a sidenote, isn't a bit strange replacing a filtered entity with null? I don't say it happens often or is a good practise but null _might_ have a business meaning that's not what a "filtered" entity was suppose to equal to.
If filters on many-to-one are needed, maybe have it declared on the <many-to-one> tag instead? From what I've understood it, it takes the "class filters" into consideration.
Finally, I might have missed something. I'm sure you have really good reasons for this breaking change, I just haven't really not got it yet. Also, I'm on a looong vacation here and haven't tried this part of NH in 2.1 - I could very much talking rubbish here if I've totally missed how it works reading this (and other) forum discussions.
Keep up the good work
Roger
________________________________
Från: nhibernate-...@googlegroups.com [nhibernate-...@googlegroups.com] för Fabio Maulo [fabio...@gmail.com]
Skickat: den 14 augusti 2009 14:41
Till: nhibernate-...@googlegroups.com
Ämne: [nhibernate-development] Re: Many to one filters
The concept of the filter is that it is applied when a query-space (table) is affected by the filter.
This should be the behaviour.
var invoice = s.CreateCriteria<Invoice>()
.UniqueResult<Invoice>();
and
invoice = s.CreateCriteria<Invoice>()
.SetFetchMode("Category", FetchMode.Eager)
.UniqueResult<Invoice>();
are two different queries and the filter may cause different behaviour.
In this case the filter shouldn't be applied in the first query and should be applied in the second queries.
With HQL all is more clear:
from Invoice
and
from Invoice i join fetch i.Category
2009/8/14 Richard Brown (gmail) <fluk...@googlemail.com<mailto:fluk...@googlemail.com>>
Is there a problem here (that is outside user control) because we implemented this feature implicitly?
With filters on classes, we add the filter inside the class mapping and this only affects queries but not Load/Get using an ID.
With many-to-one relationships (bag/set) we add an explicit filter, or the filter on the class is ignored (a collection without the filter gets everything regardless of the class filter).
With filter on many-to-one ... shouldn't we really make this explicit in the mapping?
e.g., something like:
<many-to-one name="Category" class="Category>
<filter name="validity">ValidUntil > :date</filter>
</many-to-one>
which would make the queries (and loads) eager on that property when the filter is enabled? (Or do we already do this - I couldn't find any test with an example like that)
(I'm just thinking out loud here - hopefully not talking rubbish)
From: Ayende Rahien<mailto:aye...@ayende.com>
Sent: Friday, August 14, 2009 10:40 AM
To: nhibernate-...@googlegroups.com<mailto:nhibernate-...@googlegroups.com>
Subject: [nhibernate-development] Re: Many to one filters
Problem is that eager loading is going to cause _nasty_ issues.
Thing about the potential for Cartesian products, for example, or how much extra data we would have to load.
On Fri, Aug 14, 2009 at 12:25 PM, Richard Brown (gmail) <fluk...@googlemail.com<mailto:fluk...@googlemail.com>> wrote:
I get it. I think you're right, it should eager-load to determine correct result.
From: Ayende Rahien<mailto:aye...@ayende.com>
Sent: Friday, August 14, 2009 10:23 AM
To: nhibernate-...@googlegroups.com<mailto:nhibernate-...@googlegroups.com>
Subject: [nhibernate-development] Re: Many to one filters
Richard,
It isn't working right now for a different reason, because we always put the condition in the where clause, not in the join condition.
I am talking about the actual design, not the impl. I consider the impl. buggy at the moment and will fix it soon.
As for the lazy load scenario, it doesn't work.
Imagine:
var invoice = s.Get<Invoice>(1); // select * from Invoices where Id = 1
Console.WriteLine(invoice.Category.Name<http://invoice.Category.Name>); // select * from Categories where Id =2 and date > @validDate
Now, consider what the options are.
If we lazy load category, we don't know if it is valid or not.
Because we don't know, we put a proxy there for standard lazy loading.
Next, when we do load it, we are in a conundrum. We have what is effectively an invalid object.
NH doesn't let it happen, usually.
Moreover, if we used eager loading in the same scenario, it would throw Null Ref Error.
On Fri, Aug 14, 2009 at 11:40 AM, Richard Brown (gmail) <fluk...@googlemail.com<mailto:fluk...@googlemail.com>> wrote:
Wait, I didn't get that fully. (Probably me be stupid)
If we query, and the query doesn't return the category, I expect the (lazy load) relation to filter it:
invoice.Category should be null (lazy load should filter it);
If we query, and the query does return it (eagerly), still expect the relation to be null:
invoice.Category should also be null (query should filter it);
Which isn't working?
From: Richard Brown (gmail)<mailto:fluk...@googlemail.com>
Sent: Friday, August 14, 2009 8:55 AM
To: nhibernate-development<mailto:nhibernate-...@googlegroups.com>
Subject: Re: [nhibernate-development] Many to one filters
Isn't it consistent to say that the filter will be applied if the table/entity appears in the query?
Although, I understand it looks a little cryptic, since the table might appear in the query due to a FetchMode (like your example), or a lazy="false" in the mapping (more subtle).
Roger,I agree with you, I don't think we _should_ implement filters on many to one.At the very least, they should be explicit.
To me that also seems a bit problematic, since a NULL association
would then mean either that there is no associated object or that you
can't see it. Would it be possible to detect which case it is? What
happens if I try to set it to something when there already is a
non-visible association? Would I get an unexpected exception? Or would
the existing association just be silently dropped in favor of the new
one? Could that cause an orphan? Or how to prevent that?
/Oskar
Hm...I am not sure that I am following the logic or agreeing.This is not a matter of queries, it is a matter of optimization logic.Let us say that I have a query like:from Product p where p.Name = :nameAnd I realize that I am accessing its categories, so I want to dofrom product p fetch join p.Category where p.Name = :nameI don't expect, or want, to have this changed.
oooohhhh it is the same I'm saying aboveSo, now, we can define a behaviour:
from Product p join p.Category <=== should apply filter
from Product p join fetch p.Category <== shouldn't apply filterNote: about your previous mailselect p from Category c join c.Products p <== not possible because in general c.Products does not exists (even if it can be mapped)
resuming for many-to-one:if the query has, at least, an explicit join it should apply filterif the query has a "join fetch" shouldn't apply a filter
Now examples for collections....from Person p join fetch p.Emails <<== should apply filter on collection ?The filter is Email.IsActive
This gets more complex with criteria, though.
From: Ayende RahienSent: Sunday, August 23, 2009 6:39 PMSubject: [nhibernate-development] Re: Many to one filters
From: Fabio MauloSent: Sunday, August 23, 2009 7:18 PMSubject: [nhibernate-development] Re: Many to one filters
And if the property is lazy-loaded through the domain?
From: Fabio MauloSent: Sunday, August 23, 2009 9:03 PMSubject: [nhibernate-development] Re: Many to one filters
I actually agree with that.And we can say that if you define filter for many to one, you also disable lazy loading.That would give us consistent behavior.
Yes
If filters start to change the behavior of
the query implicitly (e.g, when eager-loading a filtered entity), this
comes as a surprise to the person who writes the query. It feels like
magic - of the bad kind - and that we should avoid IMO.