I have the following code:

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

In my POCO, I have the property:

public virtual bool QCCount { get; set; }

In my mapping, I have

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

In DB2, there are no bit fields, only char(1) with '0' or '1'.

As I understand it, the props.Add("query.substitutions","true=1;false=0"); should map these 0's and 1's to boolean POCO objects, however, it doesn't seem to be working.

Do I need to add something to the mapping of the field to tell it to use this?

有帮助吗?

解决方案

I found a solution that seems to work.

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

I changed the 'Y', 'N' to '0' and '1', then map the column and it's processing fine.

Code:

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

Mapping:

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

其他提示

It seems the NHibernate DB2 dialect maps boolean to SMALLINT (https://github.com/nhibernate/nhibernate-core/blob/master/src/NHibernate/Dialect/DB2Dialect.cs):

RegisterColumnType(DbType.Boolean, "SMALLINT");

query.substitutions is for automatically replacing some tokens in your HQL queries with other tokens, and I don't think it affects reading.

If you want to use SMALLINT for boolean columns, you must inherit usertype class from BooleanType

Code:

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

Mapping:

Property(x => x.IsDeleted, map => { map.NotNullable(true); map.Type<IntBoolUserType>(); });
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top