2013-07-19 89 views
0

我有一個自定義集合,它包裝了一個.net HashSet並實現了ICollection,然後將其映射爲一個集合。我這樣做是爲了希望NHib能夠使用ICollection接口的方式來使用僅僅使用.net HashSet的方式,而不是NHib內部使用的Iesi接口。NHibernate自定義集合不會水合

保存到數據庫似乎工作正常,但我得到的異常時,保溼讓我知道我需要做的更多:

Unable to cast object of type 'NHibernate.Collection.Generic.PersistentGenericSet`1[ContactMechanisms.Domain.Emails.Email]' to type 'ContactMechanisms.Domain.Emails.EmailCollection'. 

These articles常常被視爲方法來處理自定義集合處理,但鏈接被破壞,我可以看到更多的與查詢擴展集合。

我必須使用IUserCollectionType嗎?如果有的話,任何人都有鏈接顯示示例實施?我在當前的代碼/映射中是否有一些愚蠢的行爲?

什麼是一個好的解決方案?

CODE(父實體片斷)

public class Contact : RoleEntity<Party>, IHaveContactMechanisms 
{  
    private readonly ICollection<Email> _emails = new EmailCollection(); 

    public virtual EmailCollection Emails { get { return (EmailCollection) _emails; } } 
} 

CODE(自定義集合片段)

public class EmailCollection : ContactMechanismSet<Email> { .... } 

public class ContactMechanismSet<T> : ValueObject, ICollection<T> where T : ContactMechanism 
{ 
    private readonly HashSet<T> _set = new HashSet<T>(); 
} 

MAPPING(HBM值類型集合)

<set name ="_emails" table="Emails" access="field"> 
    <key column="ContactId"></key> 
    <composite-element class="ContactMechanisms.Domain.Emails.Email, ContactMechanisms.Domain"> 
    <property name="IsPrimary" /> 
    <property name="Address" length="100"/> 
    <property name="DisplayName" length="50"/> 
    </composite-element> 
</set> 

* UPDATE *

這樣做在我的對象二傳手的作品,但 - 我可以做得更好嗎?

public virtual EmailCollection Emails { 
    get { 
     if (!(_emails is EmailCollection)) { 
      // NHibernate is giving us an enumerable collection 
      // of emails but doesn't know how to turn that into 
      // the custom collection we really want 
      // 
      _emails = new EmailCollection (_emails); 
     } 
     return (EmailCollection) _emails ; 
    } 
} 
+0

是有可能在EmailCollection實現中使用'ISet '而不是'HashSet '? – Firo

回答

2

如果EmailCollection具有參數構造那麼下面應該有可能使用較新的NH OOTB和老以註冊CollectionTypeFactory它處理的ISet .NET(可在互聯網上找到)

public class Contact : RoleEntity<Party>, IHaveContactMechanisms 
{  
    private EmailCollection _emails = new EmailCollection(); 

    public virtual EmailCollection Emails { get { return _emails; } } 
} 

public class ContactMechanismSet<T> : ValueObject, ICollection<T> where T : ContactMechanism 
{ 
    ctor() 
    { 
     InternalSet = new HashSet<T>(); 
    } 

    private ISet<T> InternalSet { get; set; } 
} 

<component name="_emails"> 
    <set name="InternalSet" table="Emails"> 
    <key column="ContactId"></key> 
    <composite-element class="ContactMechanisms.Domain.Emails.Email, ContactMechanisms.Domain"> 
     <property name="IsPrimary" /> 
     <property name="Address" length="100"/> 
     <property name="DisplayName" length="50"/> 
    </composite-element> 
    </set> 
</component>