Nhibernate-将通用IList对象映射到单个DB列中以逗号分隔的键列表

本文关键字:分隔 列表 DB IList 对象 单个 映射 Nhibernate- | 更新日期: 2023-09-27 18:27:19

我可能过于雄心勃勃,但我希望有人能提出解决方案。

我有许多UserChoice对象,如TravellingChoices、SocialingChoices和SportChoices等,在用户配置文件中,每个用户都准确地指定了他们属于哪一个,因此在DB中,他们有一个配置文件行,映射有与他们选择的选项的键相对应的INT ID。

当你用NHibernate加载配置文件时,我使用多对一映射来构建一个配置文件对象,它实际上包含TravellingChoice、SocialingChoice、SportChoice等对象本身,而不是id,这正是我想要的。

问题是,我希望人们能够搜索符合某些条件的其他用户,但你可以选择多个。例如,有两种不同旅行选择之一的用户,或者你可以选择3种运动选项进行搜索。

因此,我想在内存中有一个搜索标准对象,作为一些强类型列表,例如

IList<TravellingChoice>
IList<SocialisingChoice>

等等。

问题是,我将搜索条件对象存储在数据库中,作为具有id分隔列表的多个列例如

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

等等。。

我想做的是使用一个nhibernate映射来获取我的表,该表包含完整的if-id/comma列表中的列,并将每个列转换为具有完全填充对象的相关Typed Ilist。

那么,我如何从上面的带有id/逗号列表的表转到带有的对象

IList<TravellingChoice>
IList<SocialisingChoice>

等等。。属性?

这对Nhibernate来说是可能的还是太复杂了?

Nhibernate-将通用IList对象映射到单个DB列中以逗号分隔的键列表

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();
    }
}