1

我才开始尝试使用 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。

4

3 回答 3

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 内部为我们完成。

于 2012-10-28T08:32:31.120 回答
0

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

于 2012-10-28T17:23:55.040 回答
0

我查看了 Hibernate 社区并找到使用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() {...}
}

字节用户类型

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

这就是诀窍!

于 2012-10-29T07:01:26.607 回答