假设您有以下表格结构:
==============================
| Case |
==============================
| Id | int |
| ReferralType | varchar(10) |
+---------| ReferralId | int |---------+
| ============================== |
| | |
| | |
====================== ====================== ======================
| SourceA | | SourceB | | SourceC |
====================== ====================== ======================
| Id | int | | Id | int | | Id | int |
| Name | varchar(50) | | Name | varchar(50) | | Name | varchar(50) |
====================== ====================== ======================
基于ReferralType,ReferralId包含SourceA,SourceB或SourceC的id
我正在试图弄清楚如何使用Fluent NHibernate或简单的NHibernate将其映射到对象模型中。我尝试了很多不同的东西,但我没有成功。有什么想法吗?
对象模型可能类似于:
public class Case
{
public int Id { get; set; }
public Referral { get; set; }
}
public class Referral
{
public string Type { get; set; }
public int Id { get; set; }
public string Name { get; set; }
}
答案 0 :(得分:0)
<强>多对任何强>
如果表结构是固定的,并且您想要使用identity
id生成器,我会将Source表映射为3个单独的类,并作为any引用映射到公共接口。
class Case
{
public virtual IReferral Referral { get; set; }
}
class SourceA : IReferral
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Type { get { return "SourceA"; } }
}
interface IReferral
{
int Id { get; set; }
string Name { get; set; }
string Type { get; }
}
public class CaseMap : ClassMap<Case>
{
public CaseMap()
{
ReferencesAny(m => m.Referral)
.EntityTypeColumn("ReferralType")
.EntityIdentifierColumn("ReferralId")
.AddMetaValue<SourceA>("SourceA")
.AddMetaValue<SourceB>("SourceB")
.AddMetaValue<SourceC>("SourceC")
.IdentityType<int>();
}
}
<强>联合子类强>
另一个选项是union-subclass,带有抽象基类映射。这允许急切提取,但您不能在子类表上使用identity
生成器。
<class name="IReferral" abstract="true" table="Referral">
<id name="Id">
<generator class="hilo"/>
</id>
<property name="Name"/>
<union-subclass name="SourceA" table="SourceA">
<!-- class specific properties -->
</union-subclass>
<union-subclass name="SourceB" table="SourceB">
<!-- class specific properties -->
</union-subclass>
<union-subclass name="SourceC" table="SourceC">
<!-- class specific properties -->
</union-subclass>
</class>
<强>子类强>
如果您可以更改表格,则可以使用subclass将所有3个推荐类映射到同一个表格。
<class name="IReferral" abstract="true" table="Referral" discriminator-value="null">
<id name="Id">
<generator class="identity"/>
</id>
<discriminator column="Discriminator" not-null="true" type="System.String"/>
<property name="Name"/>
<subclass name="SourceA" discriminator-value="SourceA">
<!-- class specific properties -->
</subclass>
<subclass name="SourceB" discriminator-value="SourceB">
<!-- class specific properties -->
</subclass>
<subclass name="SourceC" discriminator-value="SourceC">
<!-- class specific properties -->
</subclass>
</class>
答案 1 :(得分:0)
我设法通过以下方式让它发挥作用:
public class Case
{
public virtual int? Id { get; set; }
public virtual CaseReferral Referral { get; set; }
}
public class CaseReferral
{
public virtual string Type { get; protected set; }
public virtual int? ReferralId { get; protected set; }
public virtual string Name { get { return null; }
//NOTE: We need this for mapping reasons
protected virtual int CaseId { get; set; }
protected CaseReferral() { }
}
public class CaseSourceAReferral : CaseReferral
{
private SourceA _sourceA;
public virtual SourceA Source
{
get { return _sourceA; }
protected set
{
_sourceA = value;
Type = "SourceA";
ReferralId = ( _sourceA != null ? _sourceA.Id : null );
}
}
public override string Name { get { return Source.Name; } }
//NOTE: Default constructor for mapping reasons
protected CaseSourceAReferral() { }
public CaseSourceAReferral( int caseId, SourceA source )
{
CaseId = caseId;
Source = source;
}
}
public class CaseMap : ClassMap<Case>
{
public CaseMap()
{
Id( c => c.Id );
References( c => c.Referral ).Column( "Id" );
}
}
public class CaseReferralMap : ClassMap<CaseReferral>
{
public CaseReferralMap()
{
Id( Reveal.Property<CaseReferral>( "CaseId") ).Column( "Id" );
Map( r => r.Type ).Column( "ReferralType" );
Map( r => r.ReferralId ).Column( "ReferralId" );
DiscriminateSubClassesOnColumn( "ReferralType" );
}
}
public class CaseSourceAReferralMap : SubclassMap<CaseSourceAReferral>
{
public CaseSourceAReferralMap()
{
DiscriminatorValue( "SourceA" );
References( r => r.Source ).Column( "ReferralId" );
}
}