tags:

views:

192

answers:

3

This question is a bit of a dupe, but I still don't understand the best way to handle flushing.

I am migrating an existing code base, which contains a lot of code like the following:

private void btnSave_Click()
{
     SaveForm();
     ReloadList();
}

private void SaveForm()
{
    var foo = FooRepository.Get(_editingFooId);

    foo.Name = txtName.Text;

    FooRepository.Save(foo);
}

private void ReloadList()
{
     fooRepeater.DataSource = FooRepository.LoadAll();
     fooRepeater.DataBind();
}

Now that I am changing the FooRepository to Nhibernate, what should I use for the FooRepository.Save method? Should the FooRepository always flush the session when the entity is saved?

+2  A: 

I'm not sure if I understand your question, but here is what I think:

Think in "putting objects to the session" instead of "getting and storing data". NH will store all new and changed objects in the session without any special call to it.

Consider this scenarios:

Data change:

  • Get data from the database with any query. The entities are now in the NH session
  • Change entities by just changing property values
  • Commit the transaction. Changes are flushed and stored to the database.

Create a new object:

  • Call a constructor to create a new object
  • Store it to the database by calling "Save". It is in the session now.
  • You still can change the object after Save
  • Commit the changes. The latest state will be stored to the database.

If you work with detached entities, you also need Update or SaveOrUpdate to put detached entities to the session.

Of course you can configure NH to behave differently. But it works best if you follow this default behaviour.

Stefan Steinegger
A: 

It doesn't matter whether or not you explicitly flush the session between modifying a Foo entity and loading all Foos from the repository. NHibernate is smart enough to auto-flush itself if you have made changes in the session that may affect the results of the query you are trying to run.

Ideally I try to use one session per "unit of work". This means one cohesive piece of work which may involve several smaller steps. If you feel that you do not have a seam in your architecture where you can achieve this, then managing the session inside the repository will also work. Just be aware that you are missing out on some of the power that NHibernate provides you.

Stefan Moser
+1  A: 

I'd vote up Stefan Moser's answer if I could - I'm still getting to grips with Nh myself but I think it's nice to be able to write code like this:

private void SaveForm()
{
    using (var unitofwork = UnitOfWork.Start())
    {
        var foo = FooRepository.Get(_editingFooId);
        var bar = BarRepository.Get(_barId);

        foo.Name = txtName.Text;
        bar.SomeOtherProperty = txtBlah.Text;

        FooRepository.Save(foo);
        BarRepository.Save(bar);

        UnitOfWork.CommitChanges();
    }
}

so this way either the whole action succeeds or it fails and rolls back, keeping flushing/transaction management outside of the Repositories.

DanB