-->
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.  [ 23 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Best Practices on Collection field Initialization and types?
PostPosted: Mon Mar 12, 2007 4:30 am 
Newbie

Joined: Fri Mar 09, 2007 11:47 am
Posts: 6
Hi all,

I would like to use generic collections as the default value of my domain class collection properties. However I can not make this work without using an Iesi.Collection Type here (Iesi.Collections.Generic.HashedSet). Is there a way to use a standard .NET generic collection like List<ICat> instead of Iesi? (we will use reflection on the domain model to auto generate a DTO assembly later, and would rather work with standard types there than custom collections)


Failing Example using List<ICat>:
Code:
class Cat : ICat
{
   private ICollection<ICat> _mates = new List<ICat>();

   [Set(0, Name = "Mates", Table = "cat_catmates")]
   [Key(1, Column="CatId")]
   [ManyToMany(2, ClassType = typeof(Cat), Column="MateId")]
   public ICollection<ICat> Mates
   {
      get { return _mates; }
   }

   public Cat(ICollection<ICat> mates)
   {
      foreach (ICat cat in mates)
      {
         this.Mates.Add(cat);
      }
   }

}


Loading instances from the database works fine, while newly created Instances (new Cat(...)) can not be saved because Hibernate throws an invalid cast exception: Unable to cast object of type 'System.Collections.Generic.List`1[CatsAndDogs.Model.Interfaces.ICat]' to type 'Iesi.Collections.Generic.ISet`1[CatsAndDogs.Model.Interfaces.ICat]'.


Working Example (Load & Save of new instances) with HashedSet:


Code:
class Cat : ICat
{
   private ICollection<ICat> _mates = new Iesi.Collections.Generic.HashedSet<ICat>();

   [Set(0, Name = "Mates", Table = "cat_catmates")]
   [Key(1, Column="CatId")]
   [ManyToMany(2, ClassType = typeof(Cat), Column="MateId")]
   public ICollection<ICat> Mates
   {
      get { return _mates; }
   }

   public Cat(ICollection<ICat> mates)
   {
      foreach (ICat cat in mates)
      {
         this.Mates.Add(cat);
      }
   }

}


Thx in advance

Jan


Top
 Profile  
 
 Post subject: Anyone?
PostPosted: Tue Mar 13, 2007 10:15 am 
Newbie

Joined: Fri Mar 09, 2007 11:47 am
Posts: 6
May be this is really stupid, but I am trying to find out how to initialize my collections for first use - and I am just confused...

so please - give me some hint how you normally handle this...

Am I supposed to:

a) initialize collections externally by setting the field to some collection instance from the outside before adding elements?

b) let them be initialized by NHibernate by asking NHibernate for new instances instead of using new to create persistable business objects?

c) initialize them in constructor / declaration by setting them to a very simple collection type instance like ArrayList (which would not allow me to return a strongly typed collection using generics.

thx

Jan


Top
 Profile  
 
 Post subject: Use as follows .....
PostPosted: Tue Mar 13, 2007 10:34 am 
Newbie

Joined: Tue Mar 13, 2007 9:53 am
Posts: 6
Location: HCL Technologies Ltd,N.M Road ,Chennai-600029,NungumBakam,India.

List allAnimals;

private return getAllAnimals(){

return allAnimals ;

}

private void setAllAnimals(List allAnimals){

this.allAnimals = allAnimals;
}


Let the hibernate to initialize collections,
But when you are updating the collection make sure
that collection referance shuld not change.

Get the existing referance and do operations on it.



May this helps you...

_________________
Cheers,
Naga Nirangen , R.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 14, 2007 9:18 pm 
Newbie

Joined: Thu Aug 10, 2006 12:27 pm
Posts: 8
What you want to do will work with NHibernate 1.2 release (right now in RC1). I don't know any other way to allow generic collection classes to work with nhibernate 1.0.4


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 15, 2007 12:54 am 
Newbie

Joined: Tue Mar 13, 2007 9:53 am
Posts: 6
Location: HCL Technologies Ltd,N.M Road ,Chennai-600029,NungumBakam,India.
Here question is not clear.Can u explain with example.

I explaind you with my example.

In general we need not initialize collections.

_________________
Cheers,
Naga Nirangen , R.


Top
 Profile  
 
 Post subject: Clarification
PostPosted: Fri Mar 16, 2007 6:11 am 
Newbie

Joined: Fri Mar 09, 2007 11:47 am
Posts: 6
Thanks for replying,

I will try to clarify:

I have some Domain Model objects, which i manage (create, load, persist etc.) using Manager classes.

Let's say in the Manager I implement a Create Method in which I want to create a cat instance and add some friends to a collection:

Code:
public ICat CreateCat(ICat bestFriend)
{
    ICat cat = new Cat();
    cat.Mates.Add(bestFriend);
    return cat;
}


now obviously, if I create the Cat using new, and don't want to initialize the collection in the manager (outside the class), the collection needs a default value, for which it seems I have to use Iesi...Generic.HashedSet<ICat>, because Hibernate wont allow me to use List<ICat>.

So my question is:

Do I have to initialize my collection fields using a Iesi...Generic.HashedSet, if I want to use generics or is this a wrong approach alltogether?

There seems to be the alternative of letting Hibernate handle object creation and initialization of collection fields. How is this done?

Thx a lot

Jan


Top
 Profile  
 
 Post subject: still curious
PostPosted: Fri Mar 23, 2007 3:48 am 
Newbie

Joined: Fri Mar 09, 2007 11:47 am
Posts: 6
any views on that?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 23, 2007 5:25 am 
Regular
Regular

Joined: Thu Nov 23, 2006 10:29 am
Posts: 106
Location: Belgium
Hello,

I believe that in order to work with IList<> you should map your collection as a 'bag' instead of a 'set'.

_________________
Please rate this post if it helped.

X.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 26, 2007 8:12 am 
Newbie

Joined: Wed Feb 21, 2007 3:33 pm
Posts: 4
I had exactly the same question, and your solution worked for me. Thanks, xasp.


Last edited by arsindelve on Mon Mar 26, 2007 8:45 am, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 26, 2007 8:13 am 
Newbie

Joined: Wed Feb 21, 2007 3:33 pm
Posts: 4
To clarify, there is one part that was not obvious (to me anyway) - the type of the property seems to have to be "IList<>" rather than "List<>", however you can still add code in the getter as follows:

if (_myCollection == null)
_myCollection = new List<MyType>();

However, none of this worked until I mapped my collection to a "bag" rather than a "set", and now it's all working perfectly.


Top
 Profile  
 
 Post subject: Re: Anyone?
PostPosted: Tue Mar 27, 2007 4:15 am 
Newbie

Joined: Mon Mar 26, 2007 3:59 am
Posts: 4
Location: Estonia
jamjam wrote:
Am I supposed to:

a) initialize collections externally by setting the field to some collection instance from the outside before adding elements?

b) let them be initialized by NHibernate by asking NHibernate for new instances instead of using new to create persistable business objects?

c) initialize them in constructor / declaration by setting them to a very simple collection type instance like ArrayList (which would not allow me to return a strongly typed collection using generics.


I'm also interested in this. I am currently initializing collections in the domain object's constructor, but the last post by arsindelve made me realize it might be more efficient to do it in the getter. Is that the preferred way to do it?

Right now I initialize collections like this:
Code:
class Product {
   private IList<Photo> _photos;

   public Product() {
      _photos = new List<Photo>();
   }

   public IList<Photo> Photos {
      get { return _photos; }
   }
}


Maybe this would be better?
Code:
class Product {
   private IList<Photo> _photos;

   public Product() { }

   public IList<Photo> Photos {
      get {
         if (_photos == null)
            _photos = new List<Photo>();

         return _photos;
      }
   }
}


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 27, 2007 5:08 am 
Newbie

Joined: Wed Feb 21, 2007 3:33 pm
Posts: 4
I can tell you that the code you've posted (second section) is exactly what I have in my application. I can't say if it's the most efficient way, or even the "proper" way so I, too, am interested in hearing how other's have done it.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 27, 2007 5:25 am 
Regular
Regular

Joined: Thu Nov 23, 2006 10:29 am
Posts: 106
Location: Belgium
I used to initialize my collections in the getter of the property.
But when moving to a new company, we agreed on always initializing the private members in the constructor (obviously this included the collections).

I can't say I prefer one way over the other.
But initialization in the constructor has the advantage that you're always certain that the collection is initialized when you're using the private member somewhere else in your code. Also: all initialization is grouped in one place, which is sometimes handy.
Of course, you'll reply that I'm not supposed to use the private member somewhere else in my code because what else do I have a getter property for ?

In conclusion: I personally don't think there's a 'best' way.

_________________
Please rate this post if it helped.

X.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 27, 2007 1:41 pm 
Senior
Senior

Joined: Sat Sep 10, 2005 3:46 pm
Posts: 178
Im not sure if this answers the question correctly or not but what I think needs to be done with NHibernate is to lazy instantiate the collection if it doesnt exist. NHibernate will create a proxy for the collection when it reconstitutes an object. You cannot be sure of which type this proxy will be so that it why you must work with interfaces instead of concrete types. If this proxy does not exist then you know the object is new and you should instantiate a new collection. This is an example of the code that I use:


Code:
public class Team{
private IList<TeamMember> _members;

public IList<TeamMember> Members{
    get{
        if(this._members == null){
           this._members = new List<TeamMember>();
        }

        return this._members;
    }
  }
}



Your internal code should never work directlly with the concrete type or directly access the private member. This will ensure that the collection is always instantiated before you access.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 28, 2007 6:59 am 
Beginner
Beginner

Joined: Tue Jan 02, 2007 5:53 pm
Posts: 42
Location: Bergen, Norway
Hi!

Interesting discussion!

I don't see the solution presented above as a real solution to the problem. I would definitly not be careless when it comes to applying the correct attribute to any of my collections.

It is very clear that you would want to conform to the set contract when you use set attribute on a collection instead of a bag. By using bag just to get the cast to work one is definately beaking the set contract! That is not good!

I believe that jamjam asks for a well established way to create new instances, either touching the real class or an established way to produce an empty hibernate proxy instance, without modifying the attributes to bag, and without having to use any of the Iesi classes.

Then something like this should work:
Code:
ICat cat = SomeFactoryUsingHibernateProxyCreation.Create(typeof(ICat));
cat.AddMate(anotherCatInstance);

dao.save(cat);


Obviously you would not like to write code like that and rather use plain old c# classes:
Code:
ICat cat = new Cat();
cat.AddMate(anotherCatInstance);

dao.save(cat);


Here, the hibernate reflection logic will instead to the conversion from any collection to the attribute defined Iesi collection, without polluting my code.

I hope anyone can give me some clues to stay on the PONO/POCO road I'm currently following or can point to some factory that will produce an empty hibernate proxy based on my interface type or my actual implementation type.

Cheers,
Steinar.[/code]

_________________
Cheers,
Steinar.


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

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.