使用如下的映射时:
<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>
答案 0 :(得分:0)
正如您所经历的那样,index
元素/映射不支持级联。而像
支持cascade
,index-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 ......