1

Disons que votre ont la structure de tableau suivant:Besoin d'aide avec NHibernate/Courant NHibernate mapping

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

Basé sur le ReferralType l'ReferralId contient id à l'SourceA, SourceB ou SourceC

Je suis essayer de comprendre comment mapper cela en utilisant NHibernate Fluent ou tout simplement NHibernate dans un modèle d'objet. J'ai essayé beaucoup de choses différentes mais je n'ai pas réussi. Des idées?

Le modèle d'objet pourrait être quelque chose comme:

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

Comment avez-vous tracer le diagramme comme ça? Par la main? – Dann

+1

Ouais c'était à la main avec notepad ++. puis collé dans –

Répondre

0

j'ai réussi à le faire fonctionner en procédant comme suit:

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

many-to-any
Si la structure de la table est fixée, et que vous souhaitez utiliser le générateur id identity, je tracerait la Source tables sous la forme de 3 classes séparées et mappées à l'interface commune en tant que référence 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
Une autre option est union-subclass avec un mappage de classe de base abstraite. Cela permet un chargement rapide, mais vous ne pouvez pas utiliser le générateur identity sur les tables de sous-classes.

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

sous-classe
Si vous pouvez changer les tables, vous pouvez mapper les 3 classes d'orientation à la même table à l'aide 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> 
+0

Je n'arrive pas à faire fonctionner votre échantillon. Je reçois un message "Pas un membre accès Nom du paramètre: expression" –

+0

J'ai réussi à le faire fonctionner (voir ma réponse). Merci pour l'aide Lachlan. –