Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Object lifecycle in NHibernate

I think I'm missing something conceptually regarding NHibernate. I have an Instrument object which maps to an instruments table in my database. I also have a BrokerInstrument object which maps to my brokerInstruments table in my database. brokerInstrumnets is a child table of instruments. My classes look like:

public class Instrument : Entity
{
    public virtual string Name { get;  set; }
    public virtual string Symbol {get;  set;}
    public virtual ISet<BrokerInstrument> BrokerInstruments { get; set; }
    public virtual bool IsActive { get; set; }        
}

public class BrokerInstrument : Entity
{
    public virtual Broker Broker { get; set; }
    public virtual Instrument Instrument { get; set; }
    public virtual decimal MinIncrement { get; set; }
}

In my unit test, if I retrieve an Instrument from the database and then delete it with ISession.Delete, it is removed from the database along with the children (I have cascade-all switched on in my mapping file). The Instrument however still exists in memory. For example:

    [Test]
    public void CascadeTest()
    {
        int instrumentId = 1;
        IInstrumentRepo instruments = DAL.RepoFactory.CreateInstrumentRepo(_session);
        Instrument i = instruments.GetById<Instrument>(instrumentId); // retrieve an instrument from the db
        foreach (BrokerInstrument bi in i.BrokerInstruments)
        {
            Debug.Print(bi.MinIncrement.ToString()); // make sure we can see the children
        }

        instruments.Delete<Instrument>(i); // physically delete the instrument row, and children from the db

        IBrokerInstrumentRepo brokerInstruments = DAL.RepoFactory.CreateBrokerInstrumentRepo(_session);
        BrokerInstrument deletedBrokerInstrument = brokerInstruments.GetById<BrokerInstrument>(1); // try and retrieve a deleted child
        Assert.That(instruments.Count<Instrument>(), Is.EqualTo(0)); // pass (a count in the db = 0)
        Assert.That(brokerInstruments.Count<BrokerInstrument>(), Is.EqualTo(0)); // pass (a count of children in the db = 0)
        Assert.That(i.BrokerInstruments.Count, Is.EqualTo(0)); // fail because we still have the i object in memory, although it is gone from the db

    }

What is best practise regarding the object in memory? I am now in an inconsistent state because I have an Instrument object in memory which does not exist in the database. I'm a novice programmer so verbose answers with links are much appreciated.

like image 338
Mark Allison Avatar asked Jan 16 '12 13:01

Mark Allison


1 Answers

A few things. Your _session is in effect your unit of work. All the work you are doing here is deleting instrument i. Maybe wrap that code in a using(_session).

When you are doing your assertions. Make a new session to do the retrieval checks.

As regards the "i" object - firstly - don't name it i as that should be only used for loop counters. Secondly, in this assertion Assert.That(i.BrokerInstruments.Count, Is.EqualTo(0)) the count of i.BrokerInstruments would not necessarily be changed unless your implementation for IInstrumentRepo.Delete(Instrument someInstrument) is explicitly setting someInstrument to null.

Hope this helps a bit.

like image 113
Nick Ryan Avatar answered Nov 04 '22 10:11

Nick Ryan