Nhibernate映射澄清wrt Map使用实体

时间:2014-02-20 01:35:36

标签: nhibernate nhibernate-mapping

使用如下的映射时:

<class name="Product">
  <id name="Id">
    <generator class="guid" />
  </id>
  <property name="Name"/>
  <map name="UserAddedFields" table="UserAddedFields" >
    <key column="parent_id"/>
    <index-many-to-many column="UserAddedFieldId" class="UserAddedField"/>
    <element column="fieldValue"/>
  </map>
</class>

我想将一个新的UserAddedField添加到我需要先保存UserAddedField的现有产品中,否则我将获得一个TransientObjectException。异常似乎意味着我可以设置一个级联动作,使其自动保存,但我尝试过的任何东西似乎都没有用。这不可能吗?

///////////////////////////////////////////////

在下面的建议之后我已经将映射更改为以下内容但是我收到了StaleStateException:批量更新从更新返回了意外的行数;实际行数:0;预期:1

      <class name="Product">
    <id name="Id">
      <generator class="guid" />
    </id>
    <property name="Name"/>
    <bag name="UserAddedFields" lazy="true" inverse="true" batch-size="25" cascade="all-delete-orphan">
      <key column="parentId" />
      <one-to-many class="UserAddedFieldSetting" />
    </bag>
  </class>
  <class name="UserAddedField" >
    <id name="Id">
      <generator class="guid" />
    </id>
    <property name="Name" />
    <property name="IsGlobal" type="bool"/>
  </class>
  <class name="UserAddedFieldSetting" >
    <id name="Id">
      <generator class="guid" />
    </id>
    <property name="FieldValue" />
    <many-to-one class="Product" name="Product" />
    <many-to-one class="UserAddedField" name="UserAddedField" cascade="all"/>
  </class>

1 个答案:

答案 0 :(得分:0)

正如您所经历的那样,index元素/映射不支持级联。而像

这样的元素

支持cascadeindex-many-to-many只是另一个索引,其性质不是级联支持。

我的建议是:不要使用地图。引入全新的对象,由表UserAddedFields表示。如果我们用代理主键扩展它,我们可以有一个像这样的对象:

public class UserAddedFieldSetting
{
   public virtual int Id { get; protected set; }

   public virtual Product Product { get; set; }
   public virtual UserAddedField UserAddedField { get; set; }
   public virtual decimal FieldValue { get; set; }

可以映射为<bag>,即:IList<UserAddedFieldSetting>。它不仅支持级联many-to-one的{​​{1}}映射,而且查询也会更加简单明了

UserAddedField

EXTEND:

所以,现在,我们有一个映射(请参阅问题中的更新部分),它正在根据需要运行 - 很好几乎。问题是,NHibernate正在我们的<bag name="UserAddedFields" lazy="true" inverse="true" batch-size="25" cascade="all-delete-orphan"> <key column="parent_id" /> <one-to-many class="UserAddedFieldSetting" /> </bag> 关系上执行SaveOrUpdate()

这里的问题是,如何确定many-to-one应该INSERT还是更新?然后NHibernate决定UPDATE ...但返回的行数为0.因为事实上没有行要更新。我们需要插入。

答案的关键在于“未保存的值”的映射,该值表示新的== “要插入”状态。

所以让我们扩展映射:

SaveOrUpdate

确保<class name="UserAddedField" > <id name="Id" unsaved-value="00000000-0000-0000-0000-000000000000"> <generator class="guid" /> </id> ... 的每个新C#实例都有

UserAddedField

现在,NHibernate,当调用SaveOrUpdate时,会知道Id = Guid.Empty; 表示INSERT ......