为什么Session.Flush()需要保持关系?

时间:2010-09-15 03:04:41

标签: c# nhibernate session many-to-many entity-relationship

我有两个实体,ShelfProduct

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上。因此,ShelfProduct之间存在单向的多对多关系。当我运行以下代码时:

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

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

NHibernate将保存ProductShelf,但不保存它们之间的关系,因此如果您检索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 个答案:

答案 0 :(得分:1)

Save仅标记要保留的实体并生成标识符。它不会持续更改数据库。

所有更改(插入,更新和删除)都在flushing执行,这可能会在不同时刻发生。

但是,也应始终使用交易。正确的工作流程是(大致):

using (var session = factory.OpenSession())
using (var tx = session.BeginTransaction())
{
    //create and manipulate objects
    session.Save(newObjectToBePersisted);
    tx.Commit();
}

答案 1 :(得分:0)

我不确定,但也许是因为主键。当您保存两个trancident对象并使用Identity作为主键生成模型时,Nhibernate不知道多对多连接表的Id。

在真实的单词用法中,你应该总是用Transactions中的实体包装所有操作。提交事务时,所有更改都将刷新到数据库。在您提交之前,为什么要尝试选择已经选择的实体?

答案 2 :(得分:0)

您使用手动冲洗模式吗?如果你将它设置为auto,它会在需要时立即执行。如果您在交易中运行,则需要执行session.getTransaction().commit()以确保更改有效。 Hibernate将在运行可能具有错误结果的查询之前或在提交事务之前刷新会话。

您可以配置hibernate以在保存父对象时保存子对象的集合。阅读有关传递持久性的部分(在下面链接的文档页面,注释中)

(免责声明:我使用java hibernate,而不是NHibernate)