Как я могу сказать NHibernate, чтобы сохранить только измененные свойства - PullRequest
6 голосов
/ 07 июня 2011

У меня есть класс Person, сопоставленный с базой данных с помощью NHibernate. Я загружаю объекты из БД и отправляю их разным клиентам. Первый клиент изменит имя и страну. Второй клиент будет изменять только свойство Name. Затем оба возвращают измененные объекты на сервер. Когда я сохраняю данные из первого клиента, а затем сохраняю правильно, имя и страна обновляются. Когда я сохраняю данные из второго клиента - у меня проблема. Это было переопределить данные от первого клиента и сохранить новое имя и начальное значение страны.

Как я могу сказать NHibernate сохранять только значение имени, а не переопределять значение страны?

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: Извините за мой плохой английский

Ответы [ 4 ]

14 голосов
/ 08 июня 2011

На самом деле, вы можете указать NHibernate специально обновить «грязные» поля, используя Dynamic Update.

Подробнее о: http://ayende.com/blog/3946/nhibernate-mapping-concurrency

2 голосов
/ 07 июня 2011

Это проблема параллелизма. Второй клиент не знает, что данные изменились с момента его чтения, поэтому их изменения перезаписывают изменения первого клиента. Это может быть обработано в NHibernate одним из нескольких методов , наиболее распространенным из которых является использование столбца версии.

Эту проблему легко предотвратить, более серьезная проблема - обеспечить хорошую обратную связь с пользователем, когда она возникает.

1 голос
/ 07 июня 2011

Ответ: ты не можешь.NH не знает, что изменилось только имя.

Вы можете избежать этого, не разрешая одновременное редактирование.Например, оптимистичным механизмом блокировки NH.Второй клиент получит StaleObjectStateException.

. Если редактирование двух клиентов фактически происходит не одновременно (но оба они основаны на одном и том же состоянии объекта), необходимо убедиться, что второй клиентполучает изменения первого перед редактированием.Например, путем извлечения фактического состояния перед открытием редактора или путем отправки измененного уведомления с сервера.

Если вы хотите сохранить параллельное редактирование, у вас есть довольно много работы.Клиент должен предоставить информацию о том, что на самом деле изменилось.Тогда вам нужно скопировать только эти значения.Это тяжелая работа.Тогда у вас все еще может быть проблема, что объединенные значения не подходят.

0 голосов
/ 07 июня 2011

Как правильно заметил Джейми Ид, проблема с параллелизмом, а не с отображением ..

Когда вы создаете отображение вашего объекта в nhibernate, все данные, которые присутствуют в этих объектах, будутсохраняться (или обновляться) в базе данных после сброса сеанса.Вы не можете назначать отдельные поля для обновления, это все или ничего.

Еще одна (не связанная) точка, ваш пример кода создает новую фабрику сеансов для каждой операции вашей сущности.Как правило, это плохая идея, поскольку фабрики сессий очень дороги в создании.Вам лучше управлять фабрикой сессий с помощью глобального контекста (синглтона), создавать его один раз и создавать сеансы (которые имеют меньший вес), когда это необходимо.

...