如何将Fluent NHibernate中的布尔字段映射到DB2 iSeries

时间:2012-11-28 15:17:33

标签: nhibernate fluent-nhibernate boolean db2-400

我有以下代码:

private static ISessionFactory CreateSessionFactory()
{
    ISessionFactory factory = null;

    var cfg = new Configuration();

    // Do this to map bool true/false to DB2 char('0') or char('1')
    var props = new Dictionary<string, string>(); 
    props.Add("query.substitutions","true=1;false=0");
    cfg.AddProperties(props);

    cfg.DataBaseIntegration(x =>
    {
        x.ConnectionString = CONNECTION_STRING;
        x.Dialect<DB2400Dialect>();
        x.Driver<DB2400Driver>();
    });

    factory = Fluently.Configure(cfg)
        .Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly()))
        .BuildSessionFactory();

    return factory;
}

在我的POCO中,我有财产:

public virtual bool QCCount { get; set; }

在我的地图中,我有

Map(x => x.QCCount, "QCNT36");

在DB2中,没有位字段,只有char(1)为'0'或'1'。

据我了解,props.Add(“query.substitutions”,“true = 1; false = 0”);应该将这些0和1映射到布尔POCO对象,但是,它似乎不起作用。

我是否需要在字段的映射中添加一些内容以告诉它使用它?

3 个答案:

答案 0 :(得分:2)

我找到了似乎有效的解决方案。

http://lostechies.com/rayhouston/2008/03/23/mapping-strings-to-booleans-using-nhibernate-s-iusertype/

我将'Y','N'更改为'0'和'1',然后映射列并且处理正常。

代码:

public class CharBoolType : IUserType
{
    public bool IsMutable
    {
        get { return false; }
    }

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

    public SqlType[] SqlTypes
    {
        get { return new[] { NHibernateUtil.String.SqlType }; }
    }

    public object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        var obj = NHibernateUtil.String.NullSafeGet(rs, names[0]);

        if (obj == null) return null;

        var trueFalse = (string)obj;

        if (trueFalse != "1" && trueFalse != "0")
            throw new Exception(string.Format("Expected data to be '0' or '1' but was '{0}'.", trueFalse));

        return trueFalse == "1";
    }

    public void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        if (value == null)
        {
            ((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value;
        }
        else
        {
            ((IDataParameter)cmd.Parameters[index]).Value = (bool)value ? "1" : "0";
        }
    }

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

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

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

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

    public new bool Equals(object x, object y)
    {
        if (ReferenceEquals(x, y)) return true;

        if (x == null || y == null) return false;

        return x.Equals(y);
    }

    public int GetHashCode(object x)
    {
        return x == null ? typeof(bool).GetHashCode() + 473 : x.GetHashCode();
    }
}

映射:

Map(x => x.QCCount, "QCNT36").CustomType<CharBoolType>();

答案 1 :(得分:1)

似乎NHibernate DB2方言将boolean映射到SMALLINT(https://github.com/nhibernate/nhibernate-core/blob/master/src/NHibernate/Dialect/DB2Dialect.cs):

RegisterColumnType(DbType.Boolean, "SMALLINT");

query.substitutions用于自动用其他标记替换HQL查询中的一些标记,我认为它不会影响阅读。

答案 2 :(得分:1)

如果要将SMALLINT用于布尔列,则必须从BooleanType继承usertype类

代码:

public class IntBoolUserType : BooleanType, IUserType
{
    public new bool Equals(object x, object y)
    {
        if (ReferenceEquals(x, y)) return true;

        if (x == null || y == null) return false;

        return x.Equals(y);
    }

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

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

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

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

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

    public override SqlType SqlType
    {
        get
        {
            return new SqlType(DbType.Int32);
        }
    }

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

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

    public new void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        var val = !((bool)value) ? 0 : 1;
        NHibernateUtil.Int32.NullSafeSet(cmd, val, index);
    }

    public object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        return NHibernateUtil.Boolean.NullSafeGet(rs, names[0]);
    }

    public override void Set(IDbCommand cmd, object value, int index)
    {
        var val = !((bool)value) ? 0 : 1;
        ((IDataParameter)cmd.Parameters[index]).Value = val;
    }
}

映射:

Property(x => x.IsDeleted, map => { map.NotNullable(true); map.Type<IntBoolUserType>(); });