Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How I can tell NHibernate to save only changed properties

I have class Person mapped to database with NHibernate. I load objects from DB and send it to different clients. First client will modify Name and Country property. Second client will modify only Name property. Then both returns modified objects to server. When I save data from first client - then saved correctly, both - name and country updated. When I save data from second client - I have problem. It was override data from first client and save new name and initial value of country.

How I can tell NHibernate to save only Name value and not override Country value?

public class Person
{
    public string Name { get; set; }
    public string Country { get; set; }
}

public static List<Person> GetEntities()
{
    var factory = CreateSessionFactory();
    using (ISession session = factory.OpenSession())
    {
        return session.CreateCriteria<Person>().List<Person>();                
    }
}

public static void SaveEntities(List<Person> entities)
{
    var factory = CreateSessionFactory();
    using (ISession session = factory.OpenSession())
    {
         using (var t = session.BeginTransaction())
         {
             foreach (var person in entities)
             {
                 session.Merge(person);
             }

             t.Commit();
        }
    }
}

P.S: Sorry for my bad english

like image 262
gagabu Avatar asked Jun 07 '11 16:06

gagabu


3 Answers

Actually, you can tell NHibernate to specifically update the "dirty" fields using Dynamic Update.

More on: http://ayende.com/blog/3946/nhibernate-mapping-concurrency

like image 109
rebelliard Avatar answered Nov 22 '22 11:11

rebelliard


This is a concurrency problem. The second client doesn't know that the data has changed since they read it, so their changes overwrite the first client's changes. This can be handled in NHibernate by one of several methods, the most common of which is to use a version column.

This problem is easy to prevent, the bigger issue is providing good feedback to the user when it occurs.

like image 36
Jamie Ide Avatar answered Nov 22 '22 11:11

Jamie Ide


The answer is: you can't. NH doesn't know that only the name changed.

You can avoid it by not allowing concurrent editing. For instance by NH's optimistic locking mechanism. The second client would get an StaleObjectStateException.

If the editing of the two clients is actually not at the same time (but both based on the same object state), you need to make sure that the second client gets the changes of the first before editing. For instance by retrieving the actual state before opening the editor or by sending a changed notification from the server.

If you want to keep the concurrent editing, you have quite some work to do. The client needs to provide the information what actually had changed. Then you need to copy only these values. This is hard work. Then you may still have the problem that the so merged values don't fit.

like image 24
Stefan Steinegger Avatar answered Nov 22 '22 12:11

Stefan Steinegger