NHibernate cannot resolve property of one to one m

2019-08-26 14:22发布

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.

1条回答
Explosion°爆炸
2楼-- · 2019-08-26 15:01

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 a JOIN against this entity. You can then refer to that join later on:

Models.RecipeMetadata metadata = null;
var q = session.QueryOver<Recipes>(() => recipe)
   .JoinAlias(r => r.Metadata, () => metadata)
   .Where(() => metadata.SkillCommon)
   .Where(p => !p.Hidden);

This appears to work great and generate the desired SQL.

查看更多
登录 后发表回答