Nhibernate - отображение общих объектов IList на разделенные запятыми списки ключей в одном столбце БД - PullRequest
3 голосов
/ 09 марта 2012

Возможно, я пытаюсь быть слишком амбициозным, но надеюсь, что кто-то сможет предложить решение.

У меня есть несколько объектов UserChoice, таких как TravellingChoices, SocialisingChoices, SportChoices и т. Д., И в профиле пользователя каждый пользователь точно указывает, к какому из них он относится, поэтому в БД он имеет одну строку профиля, сопоставленную с INT-идентификаторами, соответствующими на клавиши выбранных опций выбора.

Когда вы загружаете профиль с помощью NHibernate, я использую сопоставления многие-к-одному для создания объекта профиля, который фактически содержит сами объекты TravellingChoice, SocialisingChoice, SportChoice и т. Д., А не id, что мне и нужно.

Проблема в том, что я хочу, чтобы люди могли искать других пользователей, которые соответствуют определенным критериям, но вам разрешено выбирать несколько. Например, пользователи могут выбрать один из двух вариантов путешествия или выбрать 3 вида спорта для поиска.

Итак, объект критериев поиска, который я хотел иметь в памяти в виде строго типизированных списков, например,

IList<TravellingChoice>
IList<SocialisingChoice>

и пр.

Проблема в том, что я сохраняю объект критериев поиска в БД в виде числа столбцов со списками, разделенными идентификаторами. например,

SocialisingChoicesColumn : 1,2,6
TravellingChoicesColumn : 5,8

и т.д ..

То, что я хочу сделать, это сделать так, чтобы отображение nhibernate взяло мою таблицу со столбцами, заполненными списками идентификаторов / запятых, и преобразовало каждый из них в соответствующий типизированный список с полностью заполненными объектами.

Итак, как мне перейти из таблицы выше со списками идентификаторов / запятых к объекту с

IList<TravellingChoice>
IList<SocialisingChoice>

и т.д .. свойства?

Возможно ли это или слишком сложно для Nhibernate?

1 Ответ

4 голосов
/ 09 марта 2012

да с ICompositeUserType. Вы можете построить на этом

class MyUserType<TChoice> : ICompositeUserType
{
    public object Assemble(object cached, ISessionImplementor session, object owner)
    {
        return DeepCopy(cached);
    }

    public object DeepCopy(object value)
    {
        return ((IList<TChoice>)value).ToList();
    }

    public object Disassemble(object value, ISessionImplementor session)
    {
        return DeepCopy(value);
    }

    bool ICompositeUserType.Equals(object x, object y)
    {
        var list1 = x as IList<TChoice>;
        var list2 = y as IList<TChoice>;

        return (x == null) ? y == null : list1.SequenceEqual(list2);
    }

    public int GetHashCode(object x)
    {
        // example implementation
        var list = x as IList<TChoice>;
        unchecked
        {
            return list == null ? 0 : list.Sum(choice => choice.GetHashCode());
        }
    }

    public object GetPropertyValue(object component, int property)
    {
        // the list has no properties to get
        throw new NotSupportedException();
    }

    public bool IsMutable
    {
        get { return true; }
    }

    public object NullSafeGet(IDataReader dr, string[] names, ISessionImplementor session, object owner)
    {
        var str = (string)NHibernateUtil.String.Get(dr, names[0]);
        IList<int> ids = str.Split(',').Select(id => int.Parse(id.Trim())).ToList();
        // HACK: assuming session also implements ISession
        return ((ISession)session).QueryOver<TChoice>()
            .WhereRestrictionOn(choice => choice.Id).IsInG(ids)
            .List();
    }

    public void NullSafeSet(IDbCommand cmd, object value, int index, bool[] settable, NHibernate.Engine.ISessionImplementor session)
    {
        var list = value as IList<TChoice>;
        NHibernateUtil.String.Set(cmd, string.Join(", ", list.Select(choice => choice.Id.ToString()).ToArray()), index);
    }

    public string[] PropertyNames
    {
        get { return new string[0]; }
    }

    public IType[] PropertyTypes
    {
        get { return new IType[0]; }
    }

    public object Replace(object original, object target, NHibernate.Engine.ISessionImplementor session, object owner)
    {
        return original;
    }

    public Type ReturnedClass
    {
        get { return typeof(IList<TChoice>); }
    }

    public void SetPropertyValue(object component, int property, object value)
    {
        // the list has no properties to set
        throw new NotSupportedException();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...