Ok I've got to be doing something really stupid, but I just can't see what it is.
I have the following query:
Recipes recipe = null;
var q = session.QueryOver<Recipes>(() => recipe)
.Where(p => p.Metadata.SkillCommon)
.Where(p => !p.Hidden);
The Recipes
model has a property called Metadata
which is a one-to-one mapping to the RecipeMetadata
model. In other words, every recipe has one and only one RecipeMetadata. It's mapped like so:
HasOne(x => x.Metadata);
When I run this query, I get the exception:
An unhandled exception of type 'NHibernate.QueryException' occurred in NHibernate.dll
Additional information: could not resolve property: Metadata.SkillCommon of: KitchenPC.DB.Models.Recipes
If I remove the reference to Metadata
:
var q = session.QueryOver<Recipes>(() => recipe)
//.Where(p => p.Metadata.SkillCommon)
.Where(p => !p.Hidden);
The query works fine. Not only that, I can see the Metadata
property under the debugger and I can see the value of Metadata.SkillCommon
. So, it is mapped correctly to the database, eagerly loaded (since OneToOne mappings are always eager), and populated with the correct value. Why in the world can't I do a query on it?
It also has nothing to do with SkillCommon
(which is a Boolean). I also can't filter on other properties within Metadata
, such as numeric values.
Please point out my obviously idiotic error so I can continue on with my evening. Thanks!
Update:
After reading this article, I'm beginning to think I don't really have a One-To-One mapping. It seems like I do, because a single recipe will always have a single RecipeMetadata row, and no other Recipe will point to that same row, but perhaps this is not the case, since technically two recipes could share the same metadata with this schema, I just prevent it from happening through a unique constraint. Thoughts?
Update 2:
I switched to a many-to-one mapping, as suggested by many posts. In my Recipes
mapping I now have:
References(x => x.Metadata).Column("RecipeId");
I can now run the query:
var q = session.QueryOver<Recipes>(() => recipe)
.Fetch(prop => prop.Metadata).Eager()
.Where(p => !p.Hidden);
And the RecipeMetadata
row is joined in and everything works. However, still when I add:
.Where(p => p.Metadata.SkillCommon)
I get the same exception as above. So, this problem had nothing to do with OneToOne mappings.
Figured this out, though I'm not sure if this is the best and/or only way to do this. It seems like it should just work but sadly, no.
You need to call
.JoinAlias
and explicitly create aJOIN
against this entity. You can then refer to that join later on:This appears to work great and generate the desired SQL.