NHibernate和Byte []作为主键

时间:2012-10-27 10:30:37

标签: c# .net mysql nhibernate fluent-nhibernate

我刚刚开始尝试使用NHibernate并且无法理解以下情况,希望有人能够对它有所了解。谢谢。

我想重构从Subsonic到NHibernate的现有数据访问层。现有数据库使用BINARY(16)作为主键。在Subsonic中,将byte []作为主键处理没有问题。在NHibernate中如果我尝试映射具有byte[]数据类型的属性,我会遇到以下异常消息:

{"Illegal use of an array as an identifier (arrays don't reimplement equals)."}

我的实体和映射(使用FluentNHibernate)的示例如下:

    public class Product
    {
        public virtual byte[] Id { get; set; }
        public virtual string Name { get; set; }
        public virtual string Description { get; set; }
    }

    public ProductMapping()
    {
        Table("tblProduct");
        Id(p => p.Id).Column("prdProductGuid");
        Map(p => p.Name).Column("prdName");
        Map(p => p.Description).Column("prdDescription");
    }

有没有办法解决这个问题?谢谢。

目前正在使用.NET 4.0,NHibernate 3.3.1和MySQL 5.1.52。

3 个答案:

答案 0 :(得分:2)

我会说它比它看起来容易得多。 16个字节,很可能代表GUID(唯一标识符)。哪个用于ID比奇怪和神秘的字节数组更有意义...

只需将您的C#类更改为具有GUID类型的ID

即可
public class Product
{
    public virtual Guid Id { get; set; }
    public virtual string Name { get; set; }
    public virtual string Description { get; set; }
}

其余部分将在NHibernate中为我们完成。

答案 1 :(得分:0)

您应该能够将组件用作组合键。该组件只有byte []作为属性,但它将使您能够提供有用的GetHashCode()和Equals()实现。

答案 2 :(得分:0)

我看了一下Hibernate社区,发现a hint使用了IUserType

我创建了一个自定义类 Bytes ,它本质上是一个字节数组的序列化包装器:

[Serializable]
public class Bytes
{
    private byte[] _value;
    public byte[] Value { get { return _value; } }

    public Bytes(byte[] bytesValue)
    {
        _value = bytesValue;
    }

    public override bool Equals(object obj) {...}
    public override int GetHashCode() {...}
    public override string ToString() {...}
}

<强> BytesUserType

public class BytesUserType : IUserType
{
    private static readonly NHibernate.SqlTypes.SqlType[] _sqlTypes = { NHibernateUtil.Binary.SqlType };
    public NHibernate.SqlTypes.SqlType[] SqlTypes { get { return _sqlTypes; } }
    public Type ReturnedType { get { return typeof(Bytes); } }
    public bool IsMutable { get { return false; } }

    public object NullSafeGet(IDataReader dr, string[] names, object owner)
    {
        object obj = NHibernateUtil.Binary.NullSafeGet(dr, names[0]);
        if (obj == null)
            return null;
        var value = (byte[])obj;
        return new Bytes(value);
    }

    public void NullSafeSet(IDbCommand cmd, object obj, int index)
    {
        if (obj == null)
            ((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value;
        else
        {
            Bytes a = (Bytes)obj;
            byte[] valueBytes = a.Value;
            ((IDataParameter)cmd.Parameters[index]).Value = valueBytes;
        }
    }

    public new bool Equals(object x, object y) {...}
    public object DeepCopy(object value) {...}
    public int GetHashCode(object x) {...}
    public object Replace(object original, object target, object owner) {...}
    public object Assemble(object cached, object owner) {...}
    public object Disassemble(object value) {...}
}

更新了我的实体和映射:

public class Product
{
    public virtual Bytes Id { get; set; }
    public virtual string Name { get; set; }
    public virtual string Description { get; set; }
}

public ProductMapping()
{
    Table("tblProduct");
    Id(p => p.Id).Column("prdProductGuid").CustomType<BytesUserType>();
    Map(p => p.Name).Column("prdName");
    Map(p => p.Description).Column("prdDescription");
}

这就是诀窍!