我们目前使用NHibernate来支持灵活的实体模型。系统字段存储在一个表中,动态字段存储在扩展表中。这些表共享相同的主键。
我们使用JOIN组件来映射扩展表中的字典。 JOIN组件被映射为可选,但发生以下错误:
创建一个没有动态属性的新实体。 Hibernate在第二个表中存储一个空记录 - 除外键/主键外,所有列都存储为null。
加载创建的记录并设置动态字段。
保存更新的记录将导致错误。 NHibernate将发出一个新的插入而不是更新语句。
Nhibernate目前存在一个错误,可能与此有关: https://nhibernate.jira.com/browse/NH-2876。
我想知道目前是否有这个NHibernate Core漏洞的解决方案,或者是否有人有解决方法?
谢谢!
答案 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
存在不可阻挡的映射可能性持久化实体不一定必须在运行时表示为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。