NHibernate - сохранение огромного отдельного объекта - PullRequest
2 голосов
/ 29 декабря 2011

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

Когда Session.Update (the_big_object) вызывается во втором сеансе, NHibernate «правильно» переопределяет каждую отдельную сущность всего графа объектов в базу данных, создавая множество обновлений, даже если они не изменены. Это понятно, потому что он понятия не имеет, что было изменено за пределами сеанса. Использование Session.Merge (the_big_object) мало помогает, так как потребует большого количества запросов.

Проблема в моем случае, обычно на большом графике есть только несколько сущностей, которые фактически изменены. Я думаю о том, что вместо использования каскада для сохранения всего объекта, возможно, будет хорошей идеей сохранить грязную коллекцию сущностей в памяти и очищать их только при необходимости. Для этого мне может понадобиться добавить грязный флаг к этим классам, привязанным к их установщикам и т. Д.

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

Есть ли какие-либо предложения / подходы, которые я могу предпринять, или есть какой-то магический трюк, который я упускаю?

Большое спасибо!

Ответы [ 3 ]

2 голосов
/ 29 декабря 2011

Не похоже, что есть способ сделать то, что вы просите, если вы сами не будете отслеживать измененные сущности. Посмотрите на эту статью. Это похоже на то, что вы спрашиваете:

Каков наилучший подход для обновления только измененных свойств в NHibernate при отключении сеанса?

Edit:

Можете ли вы присоединить свой объект к сеансу, прежде чем вносить обновления? Если это так, вы можете сделать что-то вроде этого:

using(var session = sessionFactory.OpenSession())
    using(var tx = session.BeginTransaction()) 
    {
        var p = new Person {PersonId = 1};
        session.Lock(p, LockMode.None); // <-- This is the secret sauce!
        p.Firstname = "Bob";
        // No need to call session.Update(p) since p is already associated with the session.
        tx.Commit();
    }

Выше код взят из: NHibernate - пометка определенных свойств как «грязных»

0 голосов
/ 29 декабря 2011

Просто чтобы понять:

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

Я ищу способ присоединения отсоединенного объекта к сеансу без запроса БД.

0 голосов
/ 29 декабря 2011

Пара непроверенных идей:

  • Загрузить весь граф объектов во 2-м сеансе, используя запрос или доступ к любым коллекциям, которые будут загружены с отложенным доступом Затем объедините отделенный объект во 2-й сеанс; это не должно требовать каких-либо дополнительных запросов, потому что весь граф объекта будет в кеше.

  • Реализация INotifyPropertyChanged в ваших объектах и ​​отслеживание грязных объектов в объекте верхнего уровня. Это большой объем работы, если у вас на графике много разных типов.


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

...