【问题标题】:Nhibernate - Saving object with dependant tablesNhibernate - 使用依赖表保存对象
【发布时间】:2012-03-31 01:00:34
【问题描述】:

我有一个 User 对象,其中一个属性包含一个 Photos 属性,它是 IList 类型。

SQL 数据库中的表通过外键连接。即

表用户 { userid long NOT NULL....... } 表 UserPhoto { photoid long NOT NULL, userid long not null 引用 [User].UserId........ }

因此,如果没有相应的用户行,您将无法在 userphoto 中插入一行。

我想要做的是在代码中构建一个用户对象,添加一个用户照片对象的 Ilist(它必须包含一个空白的用户 ID,用户对象也是如此,因为它没有被保存和创建按身份插入)

我的映射如下

 <class name="User" table="[User]">
    <id name="UserId" column="Id">
      <generator class="identity" />
    </id>
    <bag name="Photos" order-by="DisplayOrder asc" cascade="all">      
      <key column="UserId" />
      <one-to-many class="UserPhoto" />
    </bag>
 </class>
<class name="UserPhoto" table="UserPhoto">
    <id name="PhotoId" column="Id">
      <generator class="identity" />
    </id>
    <property name="UserId" />
</class>

但是当我尝试使用 Nhibernate Session.Save(user) 保存用户对象时,它会抛出一个错误,提示外键约束失败。所以我猜测它试图在用户表之前的列表中插入用户照片,或者它没有在照片中设置新生成的用户 ID 属性并试图用空用户 ID 保存它们。

您是否必须在映射中添加一些额外的东西来表明这是一个外键列以及它适用于什么,以便 nhibernate 知道如何以正确的顺序插入相关行,以便我可以在一次插入中完成此操作?

【问题讨论】:

    标签: c# nhibernate


    【解决方案1】:

    试试这个:

     <class name="User" table="[User]">
        <id name="UserId" column="Id">
          <generator class="identity" />
        </id>
        <bag name="Photos" order-by="DisplayOrder asc" cascade="all" inverse="true">      
          <key column="UserId" />
          <one-to-many class="UserPhoto" />
        </bag>
     </class>
    <class name="UserPhoto" table="UserPhoto">
        <id name="PhotoId" column="Id">
          <generator class="identity" />
        </id>
        <many-to-one name="User" property-ref="UserId" column="UserId"/>
    </class>
    

    Inverse = true 添加到照片包中

    http://bchavez.bitarmory.com/archive/2007/10/06/nhibernate-and-inversetruefalse-attribute.aspx

    还将 UserId 元素更改为多对一用户元素

    【讨论】:

    • 好的,谢谢你的链接,有道理。不过,我仍然收到错误,从您发布的链接我得到的印象是我需要在子声明中进行 映射?如果您在上面看到我的 UserPhoto 声明,我只是将 UserId 映射为属性。这是问题吗?我需要在 UserPhoto 声明中做什么才能让它知道 FK 关系?我尝试在 UserId 上做一个简单的多对一,但它说“来自表 UserPhoto 的关联引用了一个未映射的类:System.Int32”
    • 如果你使用inverse=true,你需要在代码中管理双方的关系——更多细节请看我的回答。
    • 我已经更新了答案。尝试将 UserId 的属性引用更改为多对一用户映射,并将 UserPhoto 类更改为具有
    • 这是否意味着我需要 UserPhoto 类上的 User 类型的 User 属性?如果我按照上面的方法进行操作,我会收到消息“NHibernate.PropertynotFoundException:在类中找不到属性“用户”的 getter”
    • 是的,这是正确的。上面的评论应该说“并将 UserPhoto 类更改为具有 User 属性而不是 userID 属性”
    【解决方案2】:

    您需要将inverse="true" 添加到包中,否则NHibernate 将尝试执行插入然后更新:

    <bag name="Photos" order-by="DisplayOrder asc" cascade="all" inverse="true">      
      <key column="UserId" />
      <one-to-many class="UserPhoto" />
    </bag>
    

    【讨论】:

      【解决方案3】:

      您需要在照片集的映射中添加 inverse="true"

      <bag name="Photos" order-by="DisplayOrder asc" cascade="all" inverse="true">
      

      或者您需要将 Photo 表中的 UserID 列设为可为空。

      如果做第一个选项,需要自己配置对象之间的关系:

      var user = new User();
      var photo = new Photo();
      photo.User = user;
      user.Photos.Add(photo);
      

      使用 inverse="true" 设置,NH 将插入用户,根据身份值更新用户 ID,然后在每次插入时将设置用户 ID 的每张照片插入照片表中。

      如果没有设置 inverse="true" ,NH 将插入带有空用户 ID 的照片,为插入的照片选择所有照片 ID,然后发出更新以设置用户 ID。这将导致生成额外的 SQL 语句。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-06
        • 2018-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多