views:

2622

answers:

4

I have some entity types that I would like to lazy load. However, they have some internal (assembly) fields they expose, but are not used outside that class. These fields are compiler generated (F#) and I cannot change them. The an example exception is:

NHibernate.InvalidProxyTypeException: The following types may not be used as proxies: Mappings.MTest: field id@47 should not be public nor internal

I understand why NHibernate is doing this, and how having fields, if I accessed them, would mess up the lazy-loading properties of the proxies that are generated. However, since I know I won't be using the fields, can I override NHibernate somehow?

Is there any way I can say "ignore this field"? I'm using Fluent NHibernate, if that makes it easier.

Edit: I should also note, I'm using NHibernate 2.1.0 Alpha 2.

Edit2: The main gist here is that I want to keep LazyLoading enabled, which means I have to use the proxy generation. Disabling LazyLoading works (no proxies), but sorta defeats the purpose of a nice framework like NHibernate.

A: 

You might want to take a look at this page which gives an overview of using F# with Fluent NHibernate.

Edit I just noticed your username. Am I correct in perhaps thinking that this is your blog? How foolish of me. It does seem to address your problem though, specifically "We start off by disabling LazyLoad because most of the properties are not virtual, and NHibernate will fail to validate the mapping. Instead, we explicitly LazyLoad things, like the Store reference."? Maybe I'm just misunderstanding the problem.

Volte
That's exactly the problem. I now made virtual properties, but have no way of making the backing fields private. I don't want to disable lazy loading, I want NHibernate t just put up with it :). I can't see any technical reason it won't work, except for this cautious check it has.
MichaelGG
I guess it has more to do with the fact that the proxies cannot even be generated in the first place if there are non-virtual members since it is necessarily a subclass which overrides all members. Unfortunately I'm not familiar enough with F# to offer any specific advice.
Volte
They can, they just can't override the fields of course. See my answer.
MichaelGG
Everything I can find online indicates that NHibernate requires a complete proxy for lazy loading (for what reason specifically I couldn't say). For instance, http://groups.google.com/group/nhusers/browse_thread/thread/a6933c10ea2e0741
Volte
Oh, no, you're correct on that's what NHibernate requires. I'm just saying that it's a defensive requirement -- the accessibility modifier doesn't prevent the proxy from working. Removing the check from NHibernate's source lets me lazy-load with proxies just fine.
MichaelGG
+1  A: 

You can use the

[XmlIgnore]

attribute to decorate the fields :)

cwap
For NHibernate? It ignored it and still crashed.
MichaelGG
Weird :S I used it myself for the same kind of problem. Maybe it's because you use FluentNHibernate..
cwap
Oh that sucks :(. It'd be a cute solution. (Although, I can't actually put attributes on these fields). Do you have a reference to any docs showing what XmlIgnore controls in NHibernate? Thanks!
MichaelGG
Actually, no :) I reverse engineered the NHibernate source of the assembly I used, and found that it used the XmlReader-class.. From there on I went to MSDN and found this lovely tag :)
cwap
+5  A: 

I reassembled NHibernate (easier than getting the source and rebuilding) and removed the code that errors on internal/public fields. LazyLoading appears to work just fine without that check. (Although, I'm new to NHibernate and so there are probably scenarios I don't know about.)

Edit: Ah, there is a property, "use_proxy_validator" that will disable all validation checks. Good enough.

Fluently.Configure()
    .ExposeConfiguration(fun cfg -> 
        cfg.Properties.Add("use_proxy_validator", "false"))...
MichaelGG
+1  A: 

Can you use an Interface to declare the fields "used" ?http://nhforge.org/doc/nh/en/index.html#persistent-classes-poco-sealed

"Another possibility is for the class to implement an interface that declares all public members"

I don't know if NH use the same @transient annotation/attribute as the JAVA version to ignore a property in persistent operations.

Matthieu
F# doesn't have implicit interface implementation, and the actual field has a compiler generated name. But I like the thinking.
MichaelGG