I’ve created a new nuget package; “NHibernate.SetForNet4”.
The package is only one file that will be inserted in your project. This class contains the implementation for the Set<T> and SortedSet<T>.
After you install NHibernate.SetForNet4; the only thing you have to do is to add the collection factory to your configuration as follows:
configuration.Properties[Environment.CollectionTypeFactoryClass]
= typeof(Net4CollectionTypeFactory).AssemblyQualifiedName;
this is a sample mapping:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="NHibernateSetForNet4"
namespace="NHibernateSetForNet4">
<class name="Person">
<id name="Id">
<generator class="hilo"/>
</id>
<property name="Name" />
<property name="Age" />
<set name="Tags" access="field.camelcase">
<key column="PersonId" />
<element column="Tag" />
</set>
<set name="Childs"
access="field.camelcase"
cascade="persist"
sort="PersonByAgeComparator">
<key column="ParentId" />
<one-to-many class="Person" />
</set>
</class>
</hibernate-mapping>
this is the class:
public class Person
{
private readonly ISet<string> tags
= new HashSet<string>();
private readonly ISet<Person> childs
= new SortedSet<Person>(new PersonByAgeComparator());
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual int Age { get; set; }
public virtual ISet<string> Tags
{
get { return tags; }
}
public virtual ISet<Person> Childs
{
get
{
return childs;
}
}
}
ISet<T>, HashSet<T> and SortedSet<T> are from System.Collections.Generics (.Net 4).
All these tests are green:
[TestFixture]
public class Fixture
{
private ISessionFactory sessionFactory;
private int personId;
[TestFixtureSetUp]
public void SetUp()
{
var configuration = new Configuration();
configuration.Properties[Environment.CollectionTypeFactoryClass]
= typeof(Net4CollectionTypeFactory).AssemblyQualifiedName;
configuration.Configure();
var schemaExport = new SchemaExport(configuration);
schemaExport.Execute(true, true, false);
sessionFactory = configuration.BuildSessionFactory();
InitializeData();
}
private void InitializeData()
{
using (var s = sessionFactory.OpenSession())
using (var tx = s.BeginTransaction())
{
var person = new Person
{
Name = "Pipo"
};
person.Childs.Add(new Person { Name = "Jose", Age = 1 });
person.Childs.Add(new Person { Name = "Juan", Age = 5 });
person.Childs.Add(new Person { Name = "Francisco", Age = 10 });
person.Tags.Add("one");
person.Tags.Add("two");
person.Tags.Add("three");
s.Persist(person);
personId = person.Id;
tx.Commit();
}
}
[Test]
public void CanGetAPersonWithTags()
{
using(var s = sessionFactory.OpenSession())
using (s.BeginTransaction())
{
var person = s.Get<Person>(personId);
person.Tags.Should().Have.SameValuesAs("one", "two", "three");
}
}
[Test]
public void SortedSetShouldWork()
{
using (var s = sessionFactory.OpenSession())
using (s.BeginTransaction())
{
var person = s.Get<Person>(personId);
person.Childs
.Select(p => p.Age).ToArray()
.Should().Have.SameSequenceAs(10, 5, 1);
}
}
[Test]
public void LazyLoadShouldWork()
{
using (var s = sessionFactory.OpenSession())
using (s.BeginTransaction())
{
var person = s.Get<Person>(personId);
s.Statistics.EntityCount.Should().Be.EqualTo(1);
person.Childs.ToArray();
s.Statistics.EntityCount.Should().Be.EqualTo(4);
}
}
}
The implementation of the proxy collections is a copy from the Iesi version. Let me know if you find some bug. The raw code is here.
Note: you still need Iesi.Collections.dll somewhere because nhibernate internals are tied to these collections, but you don’t longer need to reference it in your domain.
Posted
mar 15 2011, 10:26 p.m.
by
Jose Romaniello