NHibernate Optional Join生成insert而不是update

时间:2015-03-12 19:30:03

标签: nhibernate fluent-nhibernate nhibernate-mapping

我们目前使用NHibernate来支持灵活的实体模型。系统字段存储在一个表中,动态字段存储在扩展表中。这些表共享相同的主键。

我们使用JOIN组件来映射扩展表中的字典。 JOIN组件被映射为可选,但发生以下错误:

  1. 创建一个没有动态属性的新实体。 Hibernate在第二个表中存储一个空记录 - 除外键/主键外,所有列都存储为null。

  2. 加载创建的记录并设置动态字段。

  3. 保存更新的记录将导致错误。 NHibernate将发出一个新的插入而不是更新语句。

  4. Nhibernate目前存在一个错误,可能与此有关: https://nhibernate.jira.com/browse/NH-2876

    我想知道目前是否有这个NHibernate Core漏洞的解决方案,或者是否有人有解决方法?

    谢谢!

2 个答案:

答案 0 :(得分:2)

我能够通过使用映射到指向组件上的id的函数来使代码工作:

<hibernate-mapping
xmlns="urn:nhibernate-mapping-2.2"
assembly="NHibernate.Test"
namespace="NHibernate.Test.NHSpecificTest.NH2876"
default-lazy="false">

<class name="Customer">
    <id name="Id">
        <generator class="guid" />
    </id>
    <property name="Name" column="Name" />
    <join table="CustomerData" optional="true">
        <key column="CustomerId" unique="true" />
        <component name="ExtendedData">
            <property name="CustomerId" formula="[CustomerId]" insert="false" update="false" />
            <property name="SomeData" />
        </component>
    </join>
</class>

这还要求将CustomerId属性添加到组件类中。

发生这种情况的原因是,当NHibernate拉出现有记录时,如果没有非空值,则不会填充相关组件。因此,当它检查旧的价值时,#34;当在AbstractEntityPersister中调用UpdateOrInsert时,它只看到组件属性的空对象,因此认为它是一个插入。当表中没有记录时,这是相同的行为。通过使用键字段添加映射的公式字段,组件属性在&#34;旧字段中具有值&#34;并且它正确地知道它需要执行更新。

这是一个包含额外单元测试和工作解决方案(与NHibernate.Test项目一起使用)的repo,基于此处的原始单元测试 - https://nhibernate.jira.com/browse/NH-2876

https://github.com/kfehribach/NH2876

肯特

答案 1 :(得分:1)

可以在此处找到有关动态列映射的几行:NHibernate Dynamic Columns Number。在这种情况下,这可能就是这样。

<join table="ElemntValues" >

  <key column="ElementId" />
  <dynamic-component>
    ...

但老实说,我最终得到了一个不同的解决方案。

所以这是我的C#实体(例如,联系人),其中包含一些MuchMore字段

IDictionary _muchMore;

// se the property name ... used later for mapping
public virtual IDictionary MuchMore
{
    get { return _muchMore?? (_muchMore= new Hashtable()); }
    set { _muchMore= value; }
}

现在,NHibernate

存在不可阻挡的映射可能性

4.4. Dynamic models

  

持久化实体不一定必须在运行时表示为POCO类。 NHibernate还支持动态模型(在运行时使用Dictionaries的Dictionaries)。使用这种方法,您不会编写持久化类,只能编写映射文件。

     

...

     

首先,在映射文件中, entity-name 必须声明而不是(或者除了)名称

那很酷。现在我们可以创建ContactMuchMore实体的品牌虚拟映射,它将取消连接表:

<class entity-name="ContactMuchMore"  table="Contact_MuchMore_table"
       dynamic-insert="true" dynamic-update="true" batch-size="25" >

  <id name="ID" column="Contact_ID" type="int">
    <generator class="foreign">
      <param name="property">Parent</param>
    </generator>
  </id>
  <one-to-one name="Parent" class="Contact" constrained="true" />

难以置信......我们NHibenrate确实有映射实体 - 虚拟实体。它依赖于Contact ..所以我们可以使用真正的联系人作为ID生成器和one-to-one映射

这是Contact.cs映射:

<class name="Contact"  ... >
  ...
  // here we mapp the property name
  // to our virtual entity 
  <one-to-one name="MuchMore" 
              entity-name="ContactMuchMore"  
              cascade="all" />

有一对一的黑暗面(两个表总是被加载)但可以用投影解决。使用级联全部 - 没有问题将值保存到这些表中的任何一个(联系人或contact_hasmore)。

我的回答是描述xml映射(不流畅)。但我想如果概念很清楚,我们可以使用类似的东西流利,或者特别使用xml。