为什么我的类将一个集合保存到数据库,而不将另一个保存到数据库



这让我抓狂。我可以在类上保存其中一个集合,但不能保存另一个。

我有一门课叫Category

public Category()
{
    Items = new List<Item>();
    Prices = new List<Price>();
}

这两种方法几乎完全相同。构造函数分别设置一个名为Category的属性以及它们的NamePrice

public virtual Item AddItem(string name)
{
    var item = new Item(this, name);
    Items.Add(item);
    return item;
}
public virtual Price AddPrice(decimal price)
{
    var price = new Price(this, price);
    Prices.Add(price);
    return price;
}

映射

public class CategoryMap : ClassMap<Category>
{
    public CategoryMap()
    {
       // Other properties
       HasMany(x=>x.Items).Cascade.AllDeleteOrphan();
       HasMany(x=>x.Prices).Cascade.AllDeleteOrphan();
    }
}

正如您所看到的,这两个集合的映射方式完全相同。

PriceItem的映射都具有相同的映射

References(x=>x.Category);

据我所知,这两个人几乎所有的东西都是一样的。有问题

category.AddItem(someName);
session.Save(category);    // Works
category.AddPrice(somePrice);
session.Save(category);    // Doesn't work

这些都在我用来填充测试数据库的文件中。保存项目效果良好。节省价格不会。类和映射是相同的。我想不通。

映射应该可以正常工作,因为直接调用构造函数可以正常工作

session.Save(new Price(category, 1));

那么,为什么Category保存一个集合而不保存另一个呢?我运行了profiler,该类甚至没有试图保存Price集合。

更新:

正如Gabe在评论中指出的那样,如果我交换调用,以便在Item之前调用Price,则Price会进入数据库,而Item不会。

如果我在每次更新集合后调用session.Flush(),它会正常工作。我应该这样做吗,或者有没有办法修复我的映射使其工作?

尝试交换调用的顺序(先加价格,然后加项目),看看Price映射是否真的有问题,或者问题是第二次调用失败。

关于flush-大多数情况下,您不需要显式调用flush,这是nHibernate在需要时会在后台执行的操作(此处详细信息)。刷新模式不是映射问题(它是一个会话属性,您可以设置,但通常不必设置)。

如果将代码封装在事务中,则不需要flush。如果你不是,你应该是,这可能是你的问题。

using (var tx = Session.BeginTransaction()) {
    category.AddItem(someName);
    category.AddPrice(somePrice);
    session.Save(category);
    tx.Commit();
}

更新:我想我知道你的问题是什么。给定您的代码,看起来您正在创建一个新的category对象并用数据填充它。在第一个Save()上,nHibernate执行自动刷新,因为在从数据库中获得category_id之前,它无法将其分配给子集合。但第二次,category有一个id,因此不需要立即刷新会话。nHibernate在不需要的时候不会和数据库聊天。正如我上面提到的,解决方案是总是使用事务来指定你什么时候完成你的工作。

最新更新