Нужна помощь с картографированием NHibernate / Fluent NHibernate - PullRequest
1 голос
/ 17 марта 2010

Допустим, у вас есть следующая структура таблицы:

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

Я пытаюсь выяснить, как отобразить это с помощью 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; }
}

Ответы [ 2 ]

0 голосов
/ 17 марта 2010

Мне удалось заставить его работать, выполнив следующие действия:

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" );
  }
}
0 голосов
/ 17 марта 2010

многие к любой
Если структура таблицы фиксирована и вы хотите использовать генератор идентификаторов identity, я бы сопоставил исходные таблицы как 3 отдельных класса и сопоставил бы их с общим интерфейсом как 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 с абстрактным отображением базового класса. Это позволяет быстро извлекать данные, но вы не можете использовать генератор 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>

подкласс
Если вы можете изменить таблицы, вы можете отобразить все 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>
...