我刚刚开始尝试使用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。
答案 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");
}
这就是诀窍!