将标记枚举属性映射到单独的表

时间:2012-03-28 15:18:42

标签: c# nhibernate fluent-nhibernate

想象一下这样的课程:

public class MyEntity : Entity
{
    public virtual States States { get; set; }
}

[Flags]
public enum States
{
    None,
    State1 = 1,
    State2 = 2,
    State3 = 4,
    State4 = 8
}

我想将它映射到此表:

TABLE MY_ENTITY
ID: PK
STATES_ID : FK to MY_ENTITY_STATES

TABLE MY_ENTITY_STATES
ID: PK
IS_STATE1_SET (bit)
IS_STATE2_SET (bit)
IS_STATE3_SET (bit)
IS_STATE4_SET (bit)

这可能吗?

这是一个遗留场景,我无法更改数据库。


根据要求,这里有一些示例数据:

表MY_ENTITY

ID | STATES_ID
---+----------
14 | 35

表MY_ENTITY_STATES

ID | IS_STATE1_SET | IS_STATE2_SET | IS_STATE3_SET | IS_STATE4_SET
---+---------------+---------------+---------------+--------------
35 | 0             | 1             | 0             | 1

这应该会导致States.State2 | States.State4实例中States属性中MyEntity的值为{{1}}。

2 个答案:

答案 0 :(得分:2)

这是一个两步解决方案。

首先,使用join带来MY_ENTITY_STATES记录,然后编写一个IUserType,将标志转换为列。

检查here以获取示例。

答案 1 :(得分:0)

我创建了一个简单的IUserType实现来实现映射。不需要实现ICompositeUserType

public class StatesUserType : IUserType
{
    private static readonly SqlType[] _sqlTypes = {
           NHibernateUtil.Int16.SqlType, NHibernateUtil.Int16.SqlType, 
           NHibernateUtil.Int16.SqlType, NHibernateUtil.Int16.SqlType  };

    public Type ReturnedType
    {
        get { return typeof(States); }
    }

    public SqlType[] SqlTypes
    {
        get { return _sqlTypes; }
    }

    public object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        var result = States.None;
        if (((short)rs[names[0]]) == 1)
            result |= States.State1;
        if (((short)rs[names[1]]) == 1)
            result |= States.State2;
        if (((short)rs[names[2]]) == 1)
            result |= States.State3;
        if (((short)rs[names[3]]) == 1)
            result |= States.State4;

        return result;
    }

    public void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        if (value == null)
            return;
        if (value.GetType() != typeof(States))
            return;
        var states = (States)value;
        cmd.Parameters[index] = states.HasFlag(States.State1);
        cmd.Parameters[index] = states.HasFlag(States.State2);
        cmd.Parameters[index] = states.HasFlag(States.State3);
        cmd.Parameters[index] = states.HasFlag(States.State4);
    }

    public bool IsMutable
    {
        get { return false; }
    }

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

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

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

    public bool Equals(object x, object y)
    {
        return object.Equals(x, y);
    }

    public int GetHashCode(object x)
    {
        return x.GetHashCode();
    }

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

映射需要看起来像这样:

Map(y => y.States).Columns.Add("IS_STATE1_SET", "IS_STATE2_SET",
                               "IS_STATE3_SET", "IS_STATE4_SET")
                  .CustomType<StatesUserType>();