[英]Fluent NHibernate table-per-inheritance (TPH) mapping for multi class in the hierarchy
大家好,
我正在努力解决一个 Fluent NHibernate 问题。 我的解决方案中有以下类结构模板:
class OneClass
{
public virtual string OneProp {get; set;}
}
class TwoClass : OneClass
{
public virtual string TwoProp {get; set;}
}
class ThreeClass : TwoClass
{
public virtual string ThreeProp {get; set;}
}
我想对我的类使用每个继承的表层次结构策略,以便将所有数据包含在数据库的一个表中。
如何通过 Fluent NHibernate 做到这一点?
我尝试过以下情况:
1.我为父类添加了鉴别器
public class OneClassMappingOverride : IAutoMappingOverride<OneClass>
{
public void Override(AutoMapping<OneClass> mapping)
{
mapping.DiscriminateSubClassesOnColumn("Type");
mapping.SubClass<OneClass>("OneClass");
mapping.SubClass<TwoClass>("TwoClass");
mapping.SubClass<ThreeClass>("ThreeClass");
}
}
但我遇到了异常:(XmlDocument)(56,8): XML 验证错误:命名空间 'urn:nhibernate-mapping-2.2' 中的元素 'subclass' 在命名空间 'urn: 中具有无效的子元素 'joined-subclass': nhibernate-mapping-2.2'。 预期的可能元素列表:'meta、tuplizer、synchronize、property、多对一、一对一、组件、动态组件、属性、任何、map、set、list、bag、idbag、array、primitive -array, join, subclass, loader, sql-insert, sql-update, sql-delete, resultset, query, sql-query' in namespace 'urn:nhibernate-mapping-2.2'。
因为我有以下自动生成的 NHibernate xml 映射:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class xmlns="urn:nhibernate-mapping-2.2" name="MyClass.Domain.OneClass, MyClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`OneClass`">
<cache usage="read-write" />
<id name="PersistenceId" type="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="Id" />
<generator class="Systematic.Persistence.NHibernate.NHibernateIdGenerator, Systematic.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
</id>
<discriminator type="String">
<column name="Type" />
</discriminator>
<version generated="never" name="PersistedVersion" type="System.Int64, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" unsaved-value="0">
<column name="PersistedVersion" />
</version>
<property name="OneProp" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="OneProp" length="255" />
</property>
<property name="DisplayName" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="DisplayName" length="256" index="idx__DisplayName" />
</property>
<property name="SystemName" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="SystemName" length="256" index="idx__SystemName" not-null="true" />
</property>
<property name="Version" type="System.Int64, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="Version" not-null="true" />
</property>
<property name="Description" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="Description" length="10000000" />
</property>
<many-to-one class="Systematic.Persistence.PersistenceInfo, Systematic.Api, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" fetch="join" lazy="false" name="Persistence">
<column name="Persistence_id" index="idx__Persistence" not-null="true" />
</many-to-one>
<subclass name="MyClass.Domain.TwoClass, MyClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<property name="TwoProp" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="TwoProp" length="255" />
</property>
<joined-subclass name="MyClass.Domain.ThreeClass, MyClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<key>
<column name="TwoClass_id" />
</key>
<property name="ThreeProp" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="ThreeProp" length="255" />
</property>
</joined-subclass>
</subclass>
</class>
</hibernate-mapping>
2. 我尝试添加不同的鉴别器
public class OneClassMappingOverride : IAutoMappingOverride<OneClass>
{
public void Override(AutoMapping<OneClass> mapping)
{
mapping.DiscriminateSubClassesOnColumn("OneType");
}
}
public class TwoClassMappingOverride : IAutoMappingOverride<TwoClass>
{
public void Override(AutoMapping<TwoClass> mapping)
{
mapping.DiscriminateSubClassesOnColumn("TwoType");
}
}
但是没有来自系统的任何结果(相同的异常和映射文件)
3. 我尝试使用 ClassMap<> 和 SubclassMap<>
public class OneClassMap : ClassMap<OneClass>
{
public OneClassMap()
{
DiscriminateSubClassesOnColumn("Type");
Id(x => x.Id);
Map(x => x.OneProp);
}
}
public class TwoClassMap : SubclassMap<TwoClass>
{
public TwoClassMap()
{
DiscriminatorValue("TwoType");
Map(x => x.TwoProp);
}
}
public class ThreeClassMap : SubclassMap<ThreeClass>
{
public ThreeClassMap()
{
DiscriminatorValue("ThreeType");
Map(x => x.ThreProp);
}
}
在这种情况下,我有三个表(我的数据库中的 OneClass、TwoClass 和 ThreeClass)还有以下 xml 映射文件:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class xmlns="urn:nhibernate-mapping-2.2" name="MyClass.Domain.OneClass, MyClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`OneClass`">
<cache usage="read-write" />
<id name="PersistenceId" type="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="Id" />
<generator class="Systematic.Persistence.NHibernate.NHibernateIdGenerator, Systematic.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
</id>
<version generated="never" name="PersistedVersion" type="System.Int64, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" unsaved-value="0">
<column name="PersistedVersion" />
</version>
<property name="OneProp" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="OneProp" length="255" />
</property>
<property name="DisplayName" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="DisplayName" length="256" index="idx__DisplayName" />
</property>
<property name="SystemName" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="SystemName" length="256" index="idx__SystemName" not-null="true" />
</property>
<property name="Version" type="System.Int64, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="Version" not-null="true" />
</property>
<property name="Description" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="Description" length="10000000" />
</property>
<many-to-one class="Systematic.Persistence.PersistenceInfo, Systematic.Api, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" fetch="join" lazy="false" name="Persistence">
<column name="Persistence_id" index="idx__Persistence" not-null="true" />
</many-to-one>
<joined-subclass name="MyClass.Domain.TwoClass, MyClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<key>
<column name="OneClass_id" />
</key>
<property name="TwoProp" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="TwoProp" length="255" />
</property>
<joined-subclass name="MyClass.Domain.ThreeClass, MyClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<key>
<column name="TwoClass_id" />
</key>
<property name="ThreeProp" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="ThreeProp" length="255" />
</property>
</joined-subclass>
</joined-subclass>
</class>
</hibernate-mapping>
我不知道如何解决我的问题。 也许有人帮我解决这个问题。
非常感谢。
真诚的,阿列克谢
我试图解决类似的问题。 同样在我的情况下,我在一个程序集中有一个类,并且想从这个非抽象基础继承另一个程序集中的类。 Fluent NHibernate 不会映射第二个(继承的)类。 正如上面的帖子所描述的,似乎只有在以下情况下才能映射继承层次结构
在我看来,这是域建模的一个非常严重的设计限制。 接近 Fluent NHibernate 项目的人能否确认无法从不同程序集中的非抽象类继承? 或者有人有解决这个问题的解决方案吗?
谢谢,罗兰。
我相信您的情况下的问题可能是由于层次结构中的不同类被放置在不同的程序集中引起的。 我也遇到了这个问题,看起来 Fluent 不支持这种情况。
我在这里找到了我的情况,他们通过使父类抽象来修复它。 仍在努力找出是否有其他方式或官方声明不支持它,但尚未成功。
对不起,来晚了。 但迟到总比不到好。
理想情况下,您尝试过的解决方案应该可以正常工作。 但不幸的是,FNH 并不支持它。 要使其工作,您需要实现IAutomappingConfiguration
并覆盖IsDiscriminated
方法。 像这样的东西:
class MyDefaultConfiguration : DefaultAutomappingConfiguration
{
private readonly Type[] discriminatedTypes = new[]
{
typeof(OneClass), typeof(TwoClass), typeof(ThreeClass)
};
public override bool IsDiscriminated(Type type)
{
return discriminatedTypes.Contains(type) || base.IsDiscriminated(type);
}
}
然后您可以在创建持久模型时使用此配置:
AutoMap.AssemblyOf<OneClass>(new MyDefaultConfiguration())
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.