How I can tell NHibernate to save only changed properties

你。 提交于 2019-12-23 09:30:09

问题


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


回答1:


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.




回答2:


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

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




回答3:


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.




回答4:


As Jamie Ide correctly pointed out, what you're experiencing is a concurrency problem, not a mapping problem..

When you create your nhibernate mapping of your object, whatever data is present in those objects will be saved (or updated) in the database once the session is flushed. You can not designate individual fields to update, it's all or nothing.

Just another (unrelated) point, your sample code is instantiating a new session factory on each operation of your entity. This is generally a bad idea, since session factories are expensive to create. You're better off managing your session factory through a global context (singleton), create it once, and spawn sessions (which are lighter weight objects) when needed.



来源:https://stackoverflow.com/questions/6268249/how-i-can-tell-nhibernate-to-save-only-changed-properties

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!