These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: Unable to cast object of type PersistentBag
PostPosted: Wed Nov 19, 2008 1:04 pm 
Newbie

Joined: Mon Oct 15, 2007 9:59 am
Posts: 6
Hibernate version:
2.0.1GA

Error:
Unable to cast object of type 'NHibernate.Collection.PersistentBag' to type 'Intellident.Vision.Domain.SupplyChain.Interfaces.IContents

Issue

I'm trying to implement a pure Persistence Ignorance pattern. At the moment I have:

UI
|
V
Domain Interfaces
^
|
Domain
^
|
DAL (NHibernate) - this also depends on Domain Interfaces but it doesn't show well here


and I'm using Microsoft Unity to tie it all together. I do not want any reference to the NHibernate DLL in any layer except the DAL. My mappings are also held in the DAL.

I have created a business collection that is typed and wraps an internal List<T> collection. This collection implements the IList<T> and IList
interfaces as well as some custom mehods (e.g. Sort) that are not in the interfaces themselves.

snip==>
public abstract class DomainCollection<T> : IDomainCollection<T>
{
private List<T> _list;

protected DomainCollection()
{
_list = new List<T>();
}
public void Add(T item)
{
_list.Add(item);
}
...
...
}

public interface IDomainCollection<T> : ICollection<T>, IList<T>, IList
{
...
...
}

<==snip

I've played about with this a bit so it probably isn't perfect inheritance now but you get the idea. Each business collection is of this type. I have an interface for each collection defined in my interface layer e.g.

public interface IContents: IDomainCollection<IContent>
{
}

My business class then has something like:

public interface IAsset
{
Guid Id { get; }
IContents Content{ get; }
void AddContent(IContent thing);
}

So far so good. I accept its a slight overkill on the IContents but it is purely business specific and allows extension to IContents later.

If I try the following NHibernate code in the DAL WITHOUT the IContents map

public IAssets ListAllThatAreEmpty()
{
Assets assets = new Assets();
Session.CreateCriteria(typeof(Asset))
.Add(Restrictions.Eq("Name","useme"))
.List(assets);

return assets;
}

then it works great. Assets implements IList so the collection is populated. The moment I add IContents as a property to IAsset and implement it in the concreate class such as this:

public virtual IContents Contents
{
get { return _contents; }
}

I get the error listed above.

I accept there may be an issue with my mapping file dealing with concrete classes as opposed to interfaces but I'd expect the previous NHibernate code to still work.

I really don't want to have my business classes have properties that return IList<T>. For starters, Generics screws me over as I have to return concrete classes not IList<interface types>, IList doesn't implement useful features like sort and lastly... it's just plain wrong. I have to change my domain layer for NHibernate.

When my custom collection class implements every"list" interface and property I can think of... I don't know why NHibernate can't cast to it... Have done something really stupid? - or, any advice to how to change my design keeping interface access to the domain layer and absolute domain persistence ignorance?

Mapping documents:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping
xmlns="urn:nhibernate-mapping-2.2"
namespace="Domain.Supply"
assembly="Domain.Supply"
default-access="field.camelcase-underscore">
<class name="Asset" table="Asset">
<id name="Id" column="Id" unsaved-value="00000000-0000-0000-0000-000000000000">
<generator class="guid.comb" />
</id>
<property name="Name" type="string" length="100" not-null="true" />
<bag name="Contents" table="Contents" lazy="true" inverse="true" cascade="all-delete-orphan" >
<key column="AssetId" />
<one-to-many class="Content" />
</bag>
</class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping
xmlns="urn:nhibernate-mapping-2.2"
namespace="Domain.Supply"
assembly="Domain.Supply"
default-access="field.camelcase-underscore">
<class name="Content" table="Content">
<id name="Id" column="Id" unsaved-value="00000000-0000-0000-0000-000000000000">
<generator class="guid.comb" />
</id>
<property name="Description" type="string" length="255" not-null="true" />
</class>
</hibernate-mapping>


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 24, 2008 4:50 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
Just because both classes implement the same interfaces doesn't mean you can cast them to each other ! The problem is that hibernate uses it's own collection implementations. If you want to use your own collection classes you either have to implement special IUserCollectionType's (what I read since now, doesn't seem to be easy) or you can try and wrap the collections in your collection classes.

_________________
--Wolfgang


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.