2012-09-14 107 views
1

首先,對文本的牆壁感到抱歉。nHibernate中的子類表映射

我有以下架構。請注意,User_Contact可能在ContactID中包含空值。

Schema

在類級別它以下列方式

public abstract class User : EntityBase<Guid>, IAggregateRoot 
{ 
    public User() 
    { 

    } 

    public virtual string FirstName { get; set; } 
    public virtual string LastName { get; set; } 

    protected abstract override void Validate(); 
} 

public class SiteUser : User 
{ 
    public SiteUser() { } 

    public virtual Guid ApplicationId { get; set; } 
    public virtual string UserName { get; set; } 
    public virtual string LoweredUserName { get; set; } 
    public virtual string MobileAlias { get; set; } 
    public virtual bool IsAnonymous { get; set; } 
    public virtual DateTime LastActivityDate { get; set; } 

    protected override void Validate() 
    { 
     if (this.ApplicationId == Guid.Empty) 
      base.AddBrokenRule(UserBusinessRules.ApplicationIdRequired); 

     if (this.UserName.IsNullOrEmpty()) 
      base.AddBrokenRule(UserBusinessRules.UserNameRequired); 

     if (this.LoweredUserName.IsNullOrEmpty()) 
      base.AddBrokenRule(UserBusinessRules.LoweredUserNameRequired); 

     if (this.LastActivityDate == DateTime.MinValue) 
      base.AddBrokenRule(UserBusinessRules.LastActivityDateRequired); 

    } 
} 

public class SiteContact : SiteUser 
{ 

    public SiteContact() 
    { 
    } 


    public virtual int ExternalID { get; set; } 
    //All the rest... 

    protected override void Validate() 
    { 
     //validate 
    } 
} 

然後執行所以基本上這個想法是,每一個SiteContactSiteUser但並不是每個SiteUserSiteContact

我已經完全陷入困境的是如何在地球上映射nHibernate中的這種關係。我似乎能夠檢索SiteUser但無法檢索SiteContact,這很明顯,爲什麼。我已經實現的映射導致下面的sql被執行。

SELECT this_.userid    AS UserId18_0_, 
     this_.firstname   AS FirstName18_0_, 
     this_.lastname   AS LastName18_0_, 
     //Blah blah..... 
FROM user_contact this_ 
     INNER JOIN contact this_1_ 
       ON this_.userid = this_1_.contactid //Here is the error this should be ContactID = ContactID 
     INNER JOIN aspnet_users this_2_ 
       ON this_.userid = this_2_.userid 
WHERE (CASE 
      WHEN this_.contactid IS NOT NULL THEN 1 
      ELSE 0 
     END) = '1' 

但我不能爲我的生活制定出如何解決這個問題在我的hbm映射文件。這裏是爲簡單起見省略了一些字段的文件。

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="MyProject.Namespaces.Model.Entities" assembly="MyProject.Namespaces.Model"> 


    <class name="User" table="User_Contact" lazy="true" abstract="true"> 

    <id name="ID" column="UserId" type="guid"> 
     <generator class="guid" /> 
    </id> 

    <discriminator column="ContactID" formula="(CASE WHEN ContactID IS NOT NULL THEN 1 ELSE 0 END)" /> 

    <property name="FirstName"> 
     <column name="FirstName" sql-type="nvarchar(500)" not-null="true" /> 
    </property> 

    <property name="LastName"> 
     <column name="LastName" sql-type="nvarchar(500)" not-null="true" /> 
    </property> 

    <subclass name="SiteContact" discriminator-value="1"> 
     <join table="Contact"> 
     <key column="ContactID" /> //I assume the problem is here. I have tried adding foreign-key="ContactID" to no success 

     <property name="ExternalID" insert="false" update="false"> 
      <column name="ExternalID" sql-type="int" not-null="true" /> 
     </property> 

     //The rest of the mapped columns 

     </join> 
     <join table="aspnet_Users"> 
     <key column="UserId" /> 

     <property name="ApplicationId"> 
      <column name="ApplicationId" sql-type="guid" not-null="true" /> 
     </property> 

     <property name="UserName"> 
      <column name="UserName" sql-type="nvarchar(256)" not-null="true" /> 
     </property> 

     <property name="LoweredUserName"> 
      <column name="LoweredUserName" sql-type="nvarchar(256)" not-null="true" /> 
     </property> 

     <property name="MobileAlias"> 
      <column name="MobileAlias" sql-type="nvarchar(16)" not-null="false" /> 
     </property> 

     <property name="IsAnonymous"> 
      <column name="IsAnonymous" sql-type="bit" not-null="true" /> 
     </property> 

     <property name="LastActivityDate"> 
      <column name="LastActivityDate" sql-type="datetime" not-null="true" /> 
     </property> 

     </join> 
    </subclass> 

    <subclass name="SiteUser" discriminator-value="0"> 
     <join table="aspnet_Users"> 
     <key column="UserId" /> 

     //blah blah blah 

     </join> 
    </subclass> 

    </class> 

</hibernate-mapping> 

希望有人可以告訴我,如果我甚至在這個映射的正確軌道上,也許提供一些指導?

回答

1

這似乎是一個非常複雜的映射方式。我不確定你希望在這種情況下使用繼承有什麼好處,並且我會建議使用組合(即每個表有一個類並映射關係)。

說了這麼多,你可能有你的理由,所以我建議以下實現什麼我想你想:

  1. 地圖你SiteUser類的基類,並使用一個連接從User_Contact到aspnet_Users (所以在映射中沒有用戶作爲基準)
  2. 然後使用聯合子類映射而不是子類將您的SiteContact映射爲子類,因此您不需要使用標識符。
+0

事實上,你們幾乎走在了正確的軌道上,我們確實有我們爲什麼要採取這種方法的原因,但最終卻認定它完全如你所說的「過於複雜」。所以我們最終重組了架構。話雖如此,我仍然對如何實現這種映射感到好奇,看起來您的解決方案可行。非常感謝你。 –