【问题标题】:NHibernate saving of related entitiesNHibernate 保存相关实体
【发布时间】:2012-11-22 17:20:07
【问题描述】:

我有一个基本结构。一个 User 对象和一个 UserDetails 对象。 User表有身份主键生成UserId,然后我还想为这个UserId保存一个UserDetails对象。单独执行此操作很容易,但我正在尝试找到一种方法,如果我可以一次性完成,因为 User 类包含对 UserDetails 对象的引用。例如

用户 u = new User() { Name="me", Age=17, UserDetails = new UserDetails() { Detail1 = 1 } };

所以我所要做的就是传递用户对象,然后它包含对其他相关子信息的基于对象的引用(我在这个例子中大大简化了它,但是还有几个与 UserDetails 相似的类,如 UserMatchConfiguration 等每个字段都有很多字段)

我希望能够在代码中构建对象,或者让它传递和修改,然后在父用户对象上调用 save,然后保存所有相关对象。到目前为止,我已经使用一对一映射和保存级联实现了这一点,但问题是当您创建一个新对象时,当我希望它首先保存 User 类时,所有相关类的 UserId 设置为零,然后将生成的 UserId 传播到所有相关类,然后保存它们。

到目前为止的映射如下。

<class name="User" table="[User]">
    <id name="UserId" unsaved-value="0">
      <generator class="identity" />
    </id>
    <property name="FirstName" />
    <property name="LastName" />
    <property name="EmailAddress" />
    <property name="DateOfBirth" />
    <property name="Gender" />
    <property name="PostcodePartOne" />
    <property name="PostcodePartTwo" />
    <many-to-one name="UserLocation" column="UserLocationId" />
    <property name="DateJoined" />
    <property name="LastLoggedOn" />
    <property name="Status"/>
    <property name="StatusNotes" />
    <bag name="Photos" order-by="DisplayOrder asc" inverse="true" lazy="false" cascade="all">
      <key column="UserId" />
      <one-to-many class="UserPhoto" />
    </bag>
    <bag name="Interests" inverse="true" lazy="false" cascade="all">
      <key column="UserId" />
      <one-to-many class="UserMatchInterest" />
    </bag>
    <bag name="Preferences" inverse="true" lazy="false" cascade="all">
      <key column="UserId" />
      <one-to-many class="UserPreference" />
    </bag>
    <one-to-one name="Profile" class="UserProfile" cascade="save-update" />
    <one-to-one name="MatchCriteria" class="UserMatchCriteria" />
    <one-to-one name="MatchLifestyle" class="UserMatchLifestyle" />
    <property name="LastUpdated" />
  </class>

如您所见,我现在仅使用 Profile 对象对其进行试用,以尝试使其正常工作。我怎样才能拥有它以便首先保存主用户对象,然后将 UserId 传递给其他类,因为它们都将其用作主键?

我再次无法进行级联保存,然后在每个子类上手动设置 UserId 并分别保存它们,但我试图在一次调用中完成。

【问题讨论】:

  • “传播生成的 UserId”是什么意思? NH 正在为您处理关联 - 为什么您要自己管理 id 接线?只需创建一个对象图并在父实体上调用 session.save()(记得设置保存级联)。

标签: c# nhibernate one-to-one


【解决方案1】:

我会说你快到了。你的user 类映射似乎是正确的,所以我怀疑是UserProfile

NHibernate 完全支持这种类型的关系,它是 one-to-one 映射(正如您所尝试的那样)。虽然我们看不到 UserProfile 映射,但让我们按照文档对其进行扩展:

UserProfilehbm

<class name="UserProfile" table="[UserProfile]">
  <id name="UserProfileId" column="UserId">
    <generator class="foreign">
      <param name="property">User</param>
    </generator>
  </id>
  ...
  <one-to-one name="User" class="User" constrained="true"/>
</class>

UserProfile 需要这些属性:

public class UserProfile 
{
   public virtual int UserProfileId { get; set; }
   public virtual User User { get; set; }
   ...
}

在插入之前,我们必须连接两端(这是非常重要的一步):

user.Profile =  profile;
profile.User = user;

如果user.hbm.xml 中的级联映射如下所示:

 <one-to-one name="Profile" class="UserProfile" cascade="all" />

我们可以只保存一个 user 并且所有其他实体将(以正确的方式)由 NHiberante 持久化。无论如何都不需要处理ID。

【讨论】:

  • 完美,父对象的外部生成器位和链接回属性正是我所需要的。另外,我需要做些什么来实现与包收集相同的效果?例如,我有一个 UserPhoto 类,而 UserObject 有一袋 UserPhoto 对象,我希望它保存在同一个 Save 语句中,每张照片都有一个 photoid 唯一标识符,但第二列是 UserId,它是对用户的 FK 约束。我可以让单个 user.Save 在 UserPhoto 表中创建每一行并填充 UserId 列吗?
  • 是的,NHibernate 也将涵盖这一点。这种情况下的包应该标记为反向,以避免插入然后更新。因此,如果您允许级联,无论如何这对您有用...ayende.com/blog/4043/nhibernate-mapping-list
  • 谢谢,我现在去看看那个链接。最后一个快速的,在我们讨论的第一个场景中,如果它是一个更新(假设这是使用 nhibernate 合并功能?)如果我已经设置了级联保存,有没有办法只更新它的 UserProfile 部分?假设我知道 userprofile 对象是唯一已更改的对象,并且我想避免保存整个结构。现在我在父用户上调用 save ,这是否意味着我每次都必须更新整个结构?感谢您的帮助,非常感谢
  • 绝对!唯一的问题是在插入期间(如您在他的问题中描述的那样)。选择,更新...UserProfile 将作为通常的实体。它可以被查询、改变……任何东西;)
  • 所以我可以做repository.SaveItem(user.UserProfile)?即使它被配置为用户的级联保存,如果需要,我仍然可以单独执行此操作吗?那么我需要在 UserProfile hbm.xml 的 ID 标记上添加未保存值属性吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-17
相关资源
最近更新 更多