8

我有以下两个课程:

广告

public virtual int Id { get; set;
public virtual IList<AdvertImage> AdvertImages { get; set; }

广告图片

public virtual int Id { get; set; }
public virtual string Filename { get; set;
public virtual Advert Advert { get; set; }

在数据库中,我的 AdvertImages 表具有 FK 'AdvertId',它与具有 'Id' PK 的 Adverts 表相关。

这是一对多映射,因为一个广告可以有许多图像。

我的 Fluent NHibernate 映射(为简洁而编辑)是:

广告地图

Id(x => x.Id)
  .GeneratedBy.Identity();
...
HasMany(x => x.AdvertImages)
  .KeyColumn("AdvertId")
  .Inverse();
...
Table("Adverts");

广告图像地图

Id(x => x.Id)
  .GeneratedBy.Identity();
...
References(x => x.Advert)
  .Column("AdvertId");
...
Table("AdvertImages");

我正在Advert代码中创建一个新实例,然后AdvertImagesList<AdvertImage>.

当我将我的Advert对象持久化到数据库时,我希望将 AdvertImages 插入到他们的 AdvertImages 表中,但是由于这两个表之间的关系,我需要先插入 Advert,以便生成 PK Id ,然后可以将其插入 AdvertImages 表中。(当我创建 AdvertImage 列表时,我正在填充 Filename 属性,但显然在那个阶段没有新的 AdvertId,因此希望在将广告持久保存到数据库时填充它)。

我尝试过使用不同的 Inverse() 和 Cascade 设置,但还没有成功。有人可以帮忙吗?

4

3 回答 3

10

您需要将Advert映射更改为级联:

Id(x => x.Id)
  .GeneratedBy.Identity();

HasMany(x => x.AdvertImages)
  .KeyColumn("AdvertId")
  .Inverse()
  .Cascade.AllDeleteOrphan();

Table("Adverts");

然后你应该能够做这样的事情来持久化一个Advert对象和它的孩子AdvertImage

Advert newAdvert = new Advert();
AdvertImage newImage = new AdvertImage();
newImage.Advert = newAdvert;
newAdvert.AdvertImages.Add(newImage);

using(NHibernate.ISession session = SessionFactory.GetCurrentSession())
{
    using (NHibernate.ITransaction tran = session.BeginTransaction())
    {
        session.Save(newAdvert);
        tran.Commit();
    }
}

我的实体通常包含双向一对多关系的 Add 和 Remove 方法,如下所示:

public class Advert
{
    public virtual IList<AdvertImage> AdvertImages { get; set; }

    public virtual void AddImage(AdvertImage newImage)
    {
        newImage.Advert = this;
        AdvertImages.Add(newImage);
    }
}
于 2012-06-01T18:19:38.520 回答
2

我遇到过同样的问题。我花了一段时间尝试所有不同类型的映射。然后我发现我的映射很好,实际上我需要将会话包装在事务中并在 session.SaveOrUpdate() 方法之后使用 Commit() 方法。

using(var session = sessionFactory.OpenSession()) 
using(var tx = session.BeginTransaction()) 
{ 
// execute code that uses the session 
tx.Commit(); 
}
于 2014-01-21T14:36:21.477 回答
1

对我有用的通常是将外键列设置为允许 DB 中的空值 - 这将是您的 AdvertId 列,但我不确定这是否适用于您的情况,因为您使用的是身份。NHibernate 所做的是用一个查询插入所有内容,然后将子表外键列更新为父表的正确 id。也许它也适用于你的情况。

这里有一些类似的问题可能会有所帮助:Cascade insert on one-to-many with fluent NHibernate

于 2012-06-01T16:52:11.770 回答