-->
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.  [ 11 posts ] 
Author Message
 Post subject: Beginner needs help with mapping to collections
PostPosted: Fri Jul 28, 2006 10:01 am 
Beginner
Beginner

Joined: Wed Jul 26, 2006 11:52 am
Posts: 23
Location: Edinburgh, Scotland
Hi

I'm having a problem using nhibernate to populate a property in one of my classes that is a dictionary of another class, I can get it to work if the property is defined to be of type IList but not IDictionary. There is probably an easy answer to this problem but I have been searching the forums and web for ages to no avail, help would be greatly appreciated.

I have two classes instruments and company, with the company class having a property that is a dictionary of instruments, see below:

public class Company
{
private int _id;
private string _name;
//private IList _instruments;
private Dictionary<string, Instrument> _instruments;


public virtual int id
{
set { _id = value; }
get { return _id; }
}

public virtual string name
{
set { _name = value; }
get {return _name;}
}
/*
public virtual IList instruments
{
set { _instruments = value; }
get { return _instruments; }
}
*/
public virtual Dictionary<string, Instrument> instruments
{
get { return _instruments; }
set { _instruments = value; }
}


public Company()
{
}

}


public class Instrument
{
private string _code;
private string _sedol;
private string _desc;
private int _companyId;

public virtual string code
{
get { return _code; }
set { _code = value; }
}

public virtual string sedol
{
get { return _sedol; }
set { _sedol = value; }
}

public virtual string desc
{
get { return _desc; }
set { _desc = value; }
}

public virtual int companyId
{
get { return _companyId; }
set { _companyId = value; }
}

public Instrument()
{
}

}

When I try to instantiate a collection of Comapnies as follows:

NHibernate.ICriteria compCriteria = session.CreateCriteria(typeof(Company));
IDictionary compList = (IDictionary) compCriteria.List();

I get the following error:

Unable to cast object of type 'NHibernate.Collection.Generic.PersistentGenericBag`1[System.String]' to type 'System.Collections.Generic.Dictionary`2[System.String,roysCompanyModel.Instrument]'.

I understand that this means I can't implicitly cast between Lists and Dictionaries (I wouldn't have thought you could) but I don't know how to set up the .xml mapping file so that nhibernate knows how to put a companies instrument in to a property that is a dictionary.

Can any one help, my .xml file is below?

p.s its probably obvious but i'm not an experianced .NET developer, i'm an experianced oracle developer trying to get to grips with it.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="UserNameSpace.User, roysCompanyModel" table="users">
<id name="Id" column="LogonId" type="String" length="20">
<generator class="assigned" />
</id>
<property name="UserName" column="NName" type="String" length="40"/>
<property name="Password" column="PPassword" type="String" length="20"/>
<property name="EmailAddress" type="String" length="40"/>
<property name="LastLogon" type="DateTime"/>
</class>
<class name="roysCompanyModel.Company, roysCompanyModel" table="rme_companies">
<id name="id" column="coy_code" type="int">
<generator class="assigned" />
</id>
<property name="name" column="coy_name" type="String" length="100"/>
<bag name="instruments">
<key column="inst_coy_code" />
<one-to-many
class="roysCompanyModel.Instrument, roysCompanyModel" />
</bag>
</class>
<class name="roysCompanyModel.Instrument, roysCompanyModel" table="rme_instruments">
<id name="code" column="inst_code" unsaved-value="" type="String" length="100">
<generator class="assigned" />
</id>
<property name="sedol" column="inst_sedol" type="String" length="100"/>
<property name="desc" column="inst_desc" type="String" length="100"/>
<property name="companyId" column="inst_coy_code" type="int"/>
</class>
</hibernate-mapping>


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 28, 2006 12:59 pm 
Expert
Expert

Joined: Fri May 13, 2005 5:56 pm
Posts: 308
Location: Santa Barbara, California, USA
in order to create a Dictionary, you need to make the Instruments collection a <map> in the .hbm.xml file. So, something like:
Code:
<map name="instruments">
   <key column="inst_coy_code" />
   <index column="coy_name" />
   <one-to-many class="roysCompanyModel.Instrument, roysCompanyModel" />
</map>


also, in your Domain Object, you should be programming to the IDictionary interface (just my opinion...). i'm not using 2.0 yet so i could be wrong...

Code:
public virtual IDictionary<string, Instrument> instruments
{
   get { return _instruments; }
   set { _instruments = value; }
}


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 02, 2006 9:07 am 
Beginner
Beginner

Joined: Wed Jul 26, 2006 11:52 am
Posts: 23
Location: Edinburgh, Scotland
Thanks for your help, unfortunately it doesn't seem to have solved the problem, i'm still getting a casting issue.

When I do :

Dictionary<int, Instrument> compList = (Dictionary<int, Instrument>)compCriteria.List();

I get error :

Unable to cast object of type 'NHibernate.Collection.Generic.PersistentGenericMap`2[System.Int32,roysCompanyModel.Instrument]' to type 'System.Collections.Generic.Dictionary`2[System.Int32,roysCompanyModel.Instrument]'.

Any other ideas? My XML mapping files is below. (Incidently i'm sure you're are right about the use of the interfaces, once I get this working i'll do that. )

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="UserNameSpace.User, roysCompanyModel" table="users">
<id name="Id" column="LogonId" type="String" length="20">
<generator class="assigned" />
</id>
<property name="UserName" column="NName" type="String" length="40"/>
<property name="Password" column="PPassword" type="String" length="20"/>
<property name="EmailAddress" type="String" length="40"/>
<property name="LastLogon" type="DateTime"/>
</class>
<class name="roysCompanyModel.Company, roysCompanyModel" table="rme_companies">
<id name="id" column="coy_code" type="int">
<generator class="assigned" />
</id>
<property name="name" column="coy_name" type="String" length="100"/>
<map name="instruments">
<key column="inst_coy_code"/>
<index column="inst_code" type="String" length ="100"/>
<one-to-many class="roysCompanyModel.Instrument, roysCompanyModel" />
</map>
</class>
<class name="roysCompanyModel.Instrument, roysCompanyModel" table="rme_instruments">
<id name="code" column="inst_code" unsaved-value="" type="String" length="100">
<generator class="assigned" />
</id>
<property name="sedol" column="inst_sedol" type="String" length="100"/>
<property name="desc" column="inst_desc" type="String" length="100"/>
<property name="companyId" column="inst_coy_code" type="int"/>
</class>
</hibernate-mapping>


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 02, 2006 9:38 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Don't cast to Dictionary<X,Y>. NHibernate replaces your collection with an internal collection of its own (PersistentMap in this case), and this collection is not derived from Dictionary.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 02, 2006 10:47 am 
Beginner
Beginner

Joined: Wed Jul 26, 2006 11:52 am
Posts: 23
Location: Edinburgh, Scotland
Thanks, I'm probably being stupid here...... It doesn't seem to be valid code to cast to a dictionary whoose key and value are not declared i.e the following wont compile:

Dictionary compList = (Dictionary) compCriteria.List();

If I use the interfaces and do:

IDictionary compList = (IDictionary) compCriteria.List();

the code compiles but I get run time error:

Unable to cast object of type 'System.Collections.ArrayList' to type 'System.Collections.IDictionary'.

It looks to me like I need to call a method of the Criteria class that returns a dictionary and not an arrayList? Any ideas?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 02, 2006 10:55 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Right, ICriteria.List() returns an IList and you can't cast it to IDictionary. The error in your previous post must have occurred in a different place in the program.

Why do you want to cast the result of List() to a dictionary at all? You seem to be doing something strange.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 02, 2006 11:08 am 
Beginner
Beginner

Joined: Wed Jul 26, 2006 11:52 am
Posts: 23
Location: Edinburgh, Scotland
I may be doing something strange, appologies if I am. Basically I have a Company class with a property, instruments, that is a collection of type Dictionary (IDctionary?). I want to populate the instruments property when i'm loading a Company from the Database through NHibernate. If I make the instruments property a collection of type IList everything works OK, but i want to use the dictionary collection. Does this mean that all my properties that are collections can not be of type IDictionary?

Thanks for all your help.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 02, 2006 11:35 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
ok, but what are you using the criteria for? Can you show the whole code?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 02, 2006 12:23 pm 
Beginner
Beginner

Joined: Wed Jul 26, 2006 11:52 am
Posts: 23
Location: Edinburgh, Scotland
Here is my code, is that what you meant? If I was to reinstate the declaration of compList to be of type IList, then everything would work fine....(excuse noddy comments as a beginner to .NET and NHibernate and OO in gerenal I find this helps me to understand things better.)

/* Loading all the companies. To do this we need a
* an instance of class ICriteria and use the open
* NHibernate session to fill with all the companies.
* We can then use one of ICriteria's methods to return
* a collection of instruments
*/
NHibernate.ICriteria compCriteria = session.CreateCriteria(typeof(Company));
// Set up collection of Instruents using method on iCriteria
//IList compList = compCriteria.List();
IDictionary compList = (IDictionary) compCriteria.List();

// bind to form
this.companyBindingSource.DataSource = compList;


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 02, 2006 12:59 pm 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
You can't use ICriteria's methods to return a collection of instruments - that's the problem. You are creating a criteria for Company and this means that List will return a list of Company objects to you, no matter what other methods of ICriteria you may use (in the future criteria queries will support projections so what I have just said will no longer be true, but at present it is).


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 03, 2006 4:40 am 
Beginner
Beginner

Joined: Wed Jul 26, 2006 11:52 am
Posts: 23
Location: Edinburgh, Scotland
Thanks very much for all your help. I think I unconciously switched between two seperate problems during the course of this posting. My original problem was populating the property of a class that was of type dictionary which is solved by using the map tag in the .xml mapping file instead of the bag tag. I then hit the problem of trying to call ICriteria's method to return a collection which is a different problem again and not something I really need to do at all.

Thanks again for all your help.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 11 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.