Почему Session.Flush () требуется для сохранения отношений? - PullRequest
1 голос
/ 15 сентября 2010

У меня есть две сущности: Shelf и Product:

public class Shelf
{
    public virtual IList<Product> Products { get; set; }

    public Shelf()
    {
        Products = new List<Product>();
    }
}

public class Product
{
    public virtual string Name { get; set; }
}

В сущности, Shelf может содержать множество Products, а Product можно надетьмного Shelves.Таким образом, существует однонаправленная связь «многие ко многим» между Shelf и Product.Когда я запускаю следующий код:

var shelf = new Shelf();
var product = new Product { Name = "Peas" };
shelf.Products.Add(product);

using (var session = SessionFactory.OpenSession())
{
    session.Save(shelf);
}

NHibernate сохранит Product и Shelf, но не сохранит отношения между ними, поэтому, если вы получите Shelf, онбудет содержать ноль Products.

Однако, если я добавлю вызов session.Flush(), он сохранит связь правильно, так что при получении Shelf будет возвращен один Product.

Этот пост подробно описывает мою проблему:

http://www.neeraj.name/2005/07/02/hibernate-session-close-does-not-call-session-flush.html

Однако мне было интересно , почему мне нужен этот session.Flush() звонок.Кажется нелогичным, что сохранение Shelf с правильным каскадным поведением спасет Product, но не установит отношения между ними, пока я не очистю сеанс.Мне кажется, что вызов Save() должен спасти все , а не только сам объект без их отношений.

Ответы [ 3 ]

1 голос
/ 15 сентября 2010

Save отмечает только сущность, которая будет сохранена, и генерирует идентификатор. Изменения в базе данных не сохраняются.

Все изменения (вставки, обновления и удаления) выполняются при сбросе , что может произойти в разные моменты.

Однако транзакции также должны использоваться всегда. Правильный рабочий процесс (примерно):

using (var session = factory.OpenSession())
using (var tx = session.BeginTransaction())
{
    //create and manipulate objects
    session.Save(newObjectToBePersisted);
    tx.Commit();
}
0 голосов
/ 15 сентября 2010

Вы используете ручной режим промывки? Если он установлен на авто, он сделает это, как только это необходимо. Если вы работаете в транзакции, вам нужно сделать session.getTransaction().commit(), чтобы убедиться, что изменения остаются в силе. Hibernate очистит сеанс перед выполнением запроса, который может привести к неверному результату, или перед фиксацией транзакции.

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

(Отказ от ответственности: я использую Java Hibernate, а не NHibernate)

0 голосов
/ 15 сентября 2010

Не знаю точно, но, возможно, это из-за первичных ключей. Когда вы сохраняете два нечетких объекта и используете Identity в качестве модели генерации первичного ключа, Nhibernate не знает идентификаторы для таблицы соединения многих ко многим.

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

...