2

I am having a problem when I try switching from the Castle ProxyFactoryFactory to the LinFu ProxyFactoryFactory in NHibernate.

I have an entity like this:

public class Foo
{
    private ISet<Bar> _bars = new HashedSet<Bar>();

    public virtual void AddBar(Bar bar)
    {
       if (!_bars.Contains(bar)
            _bars.Add(bar);

       bar.Foo = this;
    }
}

This is mapped with Fluent NHibernate like this:

public class FooDbMap : ClassMap<Foo>
{
     public FooDbMap()
     {
          HasMany(x => x.Bars)
              .Access.CamelCaseField(Prefix.Underscore)
              .LazyLoad()
              .KeyColumn("FooId")
              .AsSet()
              .Cache.ReadWrite();
     }
}

The relationship is bi-directional and is mapped as such on the Bar side too.

The problem occurs when I call the AddBar method. The _bars collection is null, and a NullReferenceException is thrown.

The problem goes away if I switch back to the Castle ProxyFactoryFactory.

The error doesn't occur with all mapped collections, just this one instance.

The problem still occurs even if I change _bars to readonly! So someone is managing to set a readonly field back to null, even after the field has been assigned.

Any ideas?

cbp
  • 25,252
  • 29
  • 125
  • 205
  • Your `AddBar` method is virtual, right? Shouldn't work otherwise. Are you calling the method on a `Foo` object or a proxy of it? Which NHibernate version? Have you tried the internal proxy factory of NHibernate 3.2.0? – cremor Nov 09 '11 at 08:12
  • @cremor Yes, obviously I've reduced the code for this example, but everything is generally 'as it should be'. I am actually in the process of upgrading from NH 2.1 to 3.1 (I'm not going to 3.2 yet because I'm also using NHValidator and Fluent NHibernate which don't appear to have been updated for 3.2). Everything worked fine in NH 2, although I was using the Castle proxy provider before. Also, yes, the method is being called on a proxy of the Foo object. – cbp Nov 09 '11 at 08:44
  • If I remember it correclty, LinFu (and also the internal proxy factory in 3.2) don't call the base constructors when creating a proxy. You could try this by setting a breakpoint to the line where you initialize `_bars`. But this really shouldn't be a problem because NHibernate should assign a `PersistentSet` to it before anyone can access the object. Have you tested how it behaves with default property access? – cremor Nov 09 '11 at 08:51
  • Hi, thanks for helping with this btw. I have tried creating an empty public constructor so that I can set a breakpoint and make sure that _bars is being assigned - it is. So between the time when the entity is constructed and when I call the AddBar method, _bars is set to null (even though it is readonly). I also tried removing the .Access.CamelCaseField line, the LazyLoad line, and the Cache.ReadWrite line: in all cases the problem continues. Amazingly the entity actually has a four other ISets, all similarly mapped, and they all seem to be working (at least according to my test coverage). – cbp Nov 10 '11 at 01:43
  • You could use a plain old (self implemented) property for `Bars` and map that (not the backfield), then you can place a breakpoint in the setter. – cremor Nov 10 '11 at 13:53
  • Hi cremor, good idea, but I tried it and I can't see any point where the collection is assigned as null. If I put a breakpoint on the setter I can see that the property is being set with something (not null), but the field magically reverts to null by the time AddBar is called. (Actually not that magical - I assume that because the collection is being passed in by-reference, that the actual referenced collection could be set to null somewhere else without necessarily going through the Foo.Bar setter.) – cbp Nov 14 '11 at 01:56

0 Answers0