流畅的NHibernate将非Id Guid映射到Oracle

时间:2014-01-09 15:56:53

标签: c# oracle asp.net-mvc-4 nhibernate fluent-nhibernate

我正在尝试将Guid(不是Id属性)映射到Oracle CLOB列。

在MsSQL中,我可以将Guid映射到UniqueIdentifier列,如下所示:

Map(x => x.Guid).Column("my_guid").CustomType<GuidType>();

我在我的业务实体的构造函数中生成Guid:

public MyEntity()
{
    this.Guid = Guid.NewGuid();
}

但是,当尝试将Guid映射到Oracle中的CLOB时,使用适用于MsSQL的相同映射,它总是插入一个NULL值。

如果可以像解决Guid Id字段的映射问题那样解决这个问题会很方便:

Id(x => x.Id).Column("my_guid").GeneratedBy.GuidComb();

1 个答案:

答案 0 :(得分:1)

我真的找不到一个好方法,但是,我已经提出了一个可行的解决方案。

如果我们在Oracle中使用数据类型NOT NULL VARCHAR2(32) DEFAULT SYS_GUID()创建一个列,这将在插入记录时处理Guid的生成。

但是,Oracle会生成没有连字符的Guid,因此我们得到的内容看起来像EF8FDA432CB340ADE0434C687B89F91C

不幸的是,由于这个原因,我不得不创建自己的IUserType实现来处理将带有连字符的Guid转换为存储为VARCHAR2(32)而没有连字符的Oracle的Guid。实施如下:

[Serializable]
public class OracleGuidType : IUserType
{
    SqlType[] sqlTypes;

    public OracleGuidType()
    {
        // We use DbType.String here because we are storing as a varchar
        sqlTypes = new[] { SqlTypeFactory.GetSqlType(DbType.String, 0, 0) };
    }

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

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

    public object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        if (rs[names[0]] == DBNull.Value)
        {
            return Guid.Empty;
        }

        return new Guid(rs[names[0]].ToString());
    }

    public void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        var param = (IDataParameter)cmd.Parameters[index];
        param.DbType = sqlTypes[0].DbType;
        var guid = (Guid)value;

        if (guid != Guid.Empty)
        {
            // This line removes hyphens
            param.Value = guid.ToString("N").ToUpper();
        }
        else
        {
            param.Value = DBNull.Value;
        }
    }

    public bool IsMutable
    {
        get { return false; }
    }

    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)
    {
        return x != null && x.Equals(y);
    }

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

我的NHibernate映射定义为:

Map(x => x.Guid).Column("my_guid").Generated.Insert().CustomType<OracleGuidType>();