Need help with NHibernate / Fluent NHibernate mapping

a 夏天 提交于 2019-12-03 21:36:48

many-to-any
If the table structure is fixed, and you want to use the identity id generator, I would map the Source tables as 3 separate classes and map to the common interface as an any reference.

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
Another option is union-subclass with an abstract base class mapping. This allows eager fetching, but you cannot use the identity generator on the subclass tables.

<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
If you can change the tables, you can map all 3 Referral classes to the same table using subclass.

<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>

I managed to get it working by doing the following:

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" );
  }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!