代码之家  ›  专栏  ›  技术社区  ›  Mark Boltuc

需要有关nhibernate/fluent nhibernate映射的帮助

  •  1
  • Mark Boltuc  · 技术社区  · 15 年前

    假设您的表结构如下:

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

    我想知道如何使用FluentNHibernate或简单的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 回复  |  直到 15 年前
        1
  •  0
  •   Lachlan Roche    15 年前

    许多到任何
    如果表结构是固定的,并且您希望使用 identity ID生成器,我将源表映射为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 使用抽象基类映射。这允许急取,但不能使用 身份 子类表上的生成器。

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

    <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>
    
        2
  •  0
  •   Mark Boltuc    15 年前

    我通过以下步骤使它工作:

    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" );
      }
    }