why collections typed as HashedSet<T> rather than Set<T> ?
why collections typed as HashedSet<T> rather than Set<T> ?
The NH template is hard-coded to generate collections as type Iesi.Collections.Generic.HashedSet<T> ... the problem with this type, is that the iteration order is undefined - whereas Iesi.Collections.Generic.Set<T> maintains iteration order.
This is easy enough to fix in the template of course.
However, defining "Order By" (under "Fetching" on the property sheet in ED) may not give the result you were expecting - I would consider this a bug: if I've specified that the order is important, the collection-type should be Set<T> rather than HashedSet<T>, or else this setting has no meaning.
Ideally, there should be an option to configure the default bag/set collection types. While I realize that HashedSet<T> is faster, personally I prefer Set<T>, as the unpredictable order can make it extremely hard to debug code, as some code may fail periodically or at random...
This is easy enough to fix in the template of course.
However, defining "Order By" (under "Fetching" on the property sheet in ED) may not give the result you were expecting - I would consider this a bug: if I've specified that the order is important, the collection-type should be Set<T> rather than HashedSet<T>, or else this setting has no meaning.
Ideally, there should be an option to configure the default bag/set collection types. While I realize that HashedSet<T> is faster, personally I prefer Set<T>, as the unpredictable order can make it extremely hard to debug code, as some code may fail periodically or at random...
Are you sure that is true, even for collections that have an order-by clause? (How would NH be able to return a sorted collection of nested items, if the collection-type it uses does not maintain order? I looked at the implementation of HashedSet, and it is just a simple wrapper around a Dictionary - both the IESI documentation, and MSDN references, states clearly that the Dictionary type does not maintain order.)
EDIT: the IESI HashedSet type in the source-code in the NH repository uses a different implementation - this is wrapper around Hashtable rather than Dictionary... documentation for HashedSet states that "iteration will occur in no particular order", however, the documentation for Hashtable makes no statements about order, so who knows...?
EDIT: the IESI HashedSet type in the source-code in the NH repository uses a different implementation - this is wrapper around Hashtable rather than Dictionary... documentation for HashedSet states that "iteration will occur in no particular order", however, the documentation for Hashtable makes no statements about order, so who knows...?
As you can see:
https://docs.google.com/open?id=0BxKmkm ... NmNDg5ZmQ3
When you apply an order-by clause to a mapping, NH uses a collection-type that can maintain order.
The other case would be a collection where you care about the order in which the items are added - I'm pretty sure there's a way to do that with NH, and I read somewhere that this requires NH to delete and re-save the entire collection of child-items, so I haven't tried that yet... (I will eventually, as I do have a couple of collections where the user defines the order.)
https://docs.google.com/open?id=0BxKmkm ... NmNDg5ZmQ3
When you apply an order-by clause to a mapping, NH uses a collection-type that can maintain order.
The other case would be a collection where you care about the order in which the items are added - I'm pretty sure there's a way to do that with NH, and I read somewhere that this requires NH to delete and re-save the entire collection of child-items, so I haven't tried that yet... (I will eventually, as I do have a couple of collections where the user defines the order.)
We have investigated the issue and we would like to determine what exactly does not suit you.
Currently, the following code is generated when initializing the field for the navigation property in the constructor:
The type of the _Emps field and the type of the navigation property itself are generated by Iesi.Collections.Generic.ISet<Emp>:
When getting this object, NHibernate runtime initializes the _Emps field again with the required object (PersistentGenericSet<T>, OrderedSet<T> or another one). All these types implement Iesi.Collections.Generic.ISet<Emp> and errors never occur in this case.
As we understood from your first post, it does not suit you that we generate new Iesi.Collections.Generic.HashedSet<Emp>() for the _Emps field initialization in the following code:
And you offer using Iesi.Collections.Generic.Set<T> instead, however it is an abstract class, and it is impossible to create an instance of this class.
Besides, the PersistentGenericSet<T> class, instance of which is created by NHibernate in the standard case is not a descendant of Iesi.Collections.Generic.Set<T> class, and this can cause cast exception.
Currently, the following code is generated when initializing the field for the navigation property in the constructor:
Code: Select all
this._Emps = new Iesi.Collections.Generic.HashedSet<Emp>();
Code: Select all
public virtual Iesi.Collections.Generic.ISet<Emp> Emps
{
get
{
return this._Emps;
}
set
{
this._Emps = value;
}
}
}
As we understood from your first post, it does not suit you that we generate new Iesi.Collections.Generic.HashedSet<Emp>() for the _Emps field initialization in the following code:
Code: Select all
this._Emps = new Iesi.Collections.Generic.HashedSet<Emp>();
Besides, the PersistentGenericSet<T> class, instance of which is created by NHibernate in the standard case is not a descendant of Iesi.Collections.Generic.Set<T> class, and this can cause cast exception.
So HashedSet{T} is not an alternative to Set{T} which is abstract. Thank you for explaining this.
I'm still mixed up about how this would work though.
According to IESI documentation, HashedSet{T} does not guarantee iteration order. So if you initialize a navigation-property as HashedSet{T}, that collection can't maintain order.
After you save the object, NH may replace that property with a new collection of it's own internal type, and that type may have a sense of order - but initially, NH would must populate it's own collection-type from the HashedSet{T} collection you created, in which case, it will iterate that collection in no particular order.
That doesn't cause problems?
I'm still mixed up about how this would work though.
According to IESI documentation, HashedSet{T} does not guarantee iteration order. So if you initialize a navigation-property as HashedSet{T}, that collection can't maintain order.
After you save the object, NH may replace that property with a new collection of it's own internal type, and that type may have a sense of order - but initially, NH would must populate it's own collection-type from the HashedSet{T} collection you created, in which case, it will iterate that collection in no particular order.
That doesn't cause problems?
In the latest 4.2.110 build of Entity Developer the field initialization code will create an object of the type, similar to the internal NHibernate type for this field.
The new build can be downloaded from http://www.devart.com/entitydeveloper/download.html (the trial and free versions) or from Registered Users' Area (provided that you have an active subscription).
For the detailed information about the improvements and fixes available in Entity Developer 4.2.110, please refer to
http://www.devart.com/forums/viewtopic.php?t=23135
The new build can be downloaded from http://www.devart.com/entitydeveloper/download.html (the trial and free versions) or from Registered Users' Area (provided that you have an active subscription).
For the detailed information about the improvements and fixes available in Entity Developer 4.2.110, please refer to
http://www.devart.com/forums/viewtopic.php?t=23135