views:

1329

answers:

4

Hey Everyone..

I can't get my update to work. The test fails and I do not see any update statements being sent to the database. Can someone tell me what I'm doing wrong?

This is my repository update procedure:

public void UpdateProject(Project proj)
 {

  Session.Update(proj);


 }

This is the unit test I am trying:

[Test]

    public void Can_Update_A_Project()
    {

                    var project = _projects[0];

        project.Name = "test project";



        repository.UpdateProject(project);







        var fromDb = repository.GetAProject(_projects[0].ID);

            Assert.AreEqual(project.Name, fromDb.Name);





    }

The test always fails. I see the test data being inserted and I see the select for the test.I don't see the update being performed. What am I missing?

Thanks!

+5  A: 

There are a couple of things that may be happening.

1) The update is failing and NHibernate is raising an exception that is being swallowed somewhere - that can happen depending on how you've configured things. So in VS make sure all exceptions will cause a break.

2) The update is being cached and not written directly to the DB - you can force data to be written using Repository.Flush();

3) Are you sure _projects[0] has been read from the DB - I'm assuming that's happening in a TestSetup? If not NHibernate won't be aware of that as an object which is under its 'control'.

BTW - It's good practise to read the data you are going to change within the test itself, and then undo that change, resetting the DB to it's original state. In that way your test DB won't be altered by your testing.

BTW2 - In the above test, if project.Name has already been updated once, ie the test has run succesfully. Then next time around the test will suceed even if the update itself fails. A way to avoid this - append a DateTime to the project.Name, don't set it to a fixed value.

MrTelly
I believe the 2nd option (calling flush) will indeed be the solution. :)
Frederik Gheysels
+2  A: 

Another thing is this: when you save an entity using a session and you load the same entity from the same session using the entity's ID, you will get the same instance that you saved - regardless of whether any inserts or updates have been issued to the database.

That's because of NHibernate's 1st level cache, which is an identity map that belongs to the session.

If you want your test to check what was actually written to the database, you may do it like so:

session.Save(someEntity);
session.Flush(); // forces the entity to be inserted
session.Clear(); // clears the session's identity map, thus
                 // detaching someEntity from the session

var loadedEntity = session.Get<EntityType>(someEntity.Id);

// now you may compare the fields of someEntity and loadedEntity
// to verify that they were actually persisted
mookid8000
A: 

You, my friend, are a wealth of NHibernate knowledge. Thanks for your time. I'm going to start making changes according to your suggestions. I will report my finding here.

Thanks again!

+1  A: 

ISession.Update in NHibernate does not commit changes to the database. It is used to update transient instances in a different session from the one that was used to retrieve the instance (see here for details). Changes are sent to the database when a session is flushed. By default, sessions operate in FlushOnCommit mode, which means the changes to the objects will be sent to the database when the NHibernate transaction is committed (see here for details on the different flush modes).

Sean Carpenter