我有一个自定义集合,它包装.net HashSet并实现ICollection,然后我将其映射为一个集合。我之所以这样做是希望NHib能够使用ICollection接口,就像使用.net HashSet时一样,而不是Iesi那个 NHib在内部使用。
保存到数据库似乎工作正常,但保湿时我得到的例外让我知道我需要做更多:
Unable to cast object of type 'NHibernate.Collection.Generic.PersistentGenericSet`1[ContactMechanisms.Domain.Emails.Email]' to type 'ContactMechanisms.Domain.Emails.EmailCollection'.
These articles经常被引用作为处理自定义集合处理的方法,但是链接被破坏了,我看到的内容更多地涉及使用扩展来查询集合。
我必须使用IUserCollectionType吗?任何人都有一个链接显示示例实现,如果是这样?我目前的代码/映射中有什么傻事吗?
什么是好的解决方案?
public class Contact : RoleEntity<Party>, IHaveContactMechanisms
{
private readonly ICollection<Email> _emails = new EmailCollection();
public virtual EmailCollection Emails { get { return (EmailCollection) _emails; } }
}
public class EmailCollection : ContactMechanismSet<Email> { .... }
public class ContactMechanismSet<T> : ValueObject, ICollection<T> where T : ContactMechanism
{
private readonly HashSet<T> _set = new HashSet<T>();
}
<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>
在我的对象设置器中执行以下操作,但是 - 我可以做得更好吗?
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 :(得分:2)
如果EmailCollection有一个无参数构造函数,那么新的NH ootb应该可以使用以下版本,并且注册处理.NET ISet的CollectionTypeFactory(可以在Internet中找到)可以使用以下版本
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>