0
votes

Iam testing the capabilities of NHibernate framework and I am currently stuck with mapping a collection of collections. While mapping simple collection of objects, like:

public virtual IList<IProduct> SomeProduct { get; set; }

I simply used

HasMany(x => x.Products).Cascade.All();

And then I mapped the IProduct interface.

But now, I have to implement mapping for this property:

private readonly IEnumerable<IReadOnlyList<Guid>> _complicatedEnumerableData;

public IEnumerable<IReadOnlyList<Guid>> ComplicatedEnumerableData
{
    get { return _complicatedEnumerableData; }
}

I have tried similar approach as for the collection of standard objects, but I ended up with database table without any reference to IReadOnlyList<Guid> element.

Regarding to this question : Fluent Nhibernate map list of lists , it is not possible to map nested collections in Fluent NHibernate.

My question is - is it somehow possible using standard NHibernate (no Fluent) ?

1
You could wrap your Guid list in an object... - user995219
Yes, that would basicaly be the same as the first example I had (the IList<IProduct>, while I can store additional List in the Product class)...I was just curious whether I could map nested collection directly. - JakubJ

1 Answers

1
votes

You did not specify the database layout so here is one way of doing it which stores the inner list as value.

HasMany(x => x).Element("somecolumn", e => e.Type<ListOfGuidsUserType>());

and usertype

public class ListOfGuidsUserType : IUserType
{
    public int GetHashCode(object x)
    {
        return ((IEnumerable<Guid>)x).Count();
    }

    public object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        var value = (string)NHibernateUtil.String.Get(rs, names[0]);
        return value.Split(',').Select(Guid.Parse).ToList();
    }

    public void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        NHibernateUtil.String.Set(cmd, string.Join(",", (IEnumerable<Guid>)value), index);
    }

    public object DeepCopy(object value)
    {
        return ((IEnumerable<Guid>)value).ToList();
    }

    public object Replace(object original, object target, object owner)
    {
        return DeepCopy(original);
    }

    public object Assemble(object cached, object owner)
    {
        return DeepCopy(cached);
    }

    public object Disassemble(object value)
    {
        return DeepCopy(value);
    }

    public SqlType[] SqlTypes
    {
        get { return SqlTypeFactory.GetString(1000); }
    }

    public Type ReturnedType
    {
        get { return typeof(IEnumerable<Guid>); }
    }

    public bool IsMutable
    {
        get { return true; }
    }
}