İkili türden birincil anahtar (16) içeren tabloları içeren eski bir şema var - diğer sütunların bir MD5 karması. NHibernate, Eşitleri uygulamadığı için bir anahtar olarak bayt [] ile çalışmaz, bu yüzden bunu özel bir biçimde paketledim ve NHIbernate'i bir IUserType uygulamasıyla sağladım. MD5Hash bir sınıf değil, bir yapı olduğuna dikkat edin. Ben onun anahtar olarak MD5Hash kullanan bir türe çoktan-bir eşleme yaratana kadarNHibernate: Bir birincil anahtarı birincil anahtar olarak kullanma
public struct MD5Hash : IComparable, IComparable<MD5Hash>, IEquatable<MD5Hash> {
private readonly byte[] contents;
...
}
Her şey iyi çalıştı.
public class Referenced : IEquatable<Referenced> {
...
public virtual MD5Hash Id { get; set; }
public virtual string Name { get; set; } // must NOT be null
...
}
public class Referencer : IEquatable<Referencer> {
...
public virtual MD5Hash Id { get; set; }
public virtual Referenced Other { get; set } // may be null
...
}
I tipi referencer nesneleri yük girişiminde NHibernate satır bir BOŞ değer içerdiğinde Referans tip ait bir nesne oluşturmak üzere çalışır, böylece anahtar için bir boş değer bkz referencer atamak etmez ve veritabanında Referencer'ı güncelleyin. Başvurulan bir null olmayan sütuna eşlenen bir özelliğe sahip olduğundan, NHibernate bir istisna oluşturur. İstediğim şey, NHibernate'in Other özelliğini null değerine ayarlamasıdır.
MD5Hash'ın tanımını struct yerine bir sınıf olarak değiştirebilirim ancak kodda, MD5Hash'ın hiçbir zaman boş bırakılamayacağını varsayarak, başka bir çözüm aramayacağım bilinmeyen bir yer var.
özel türü için kod ...
internal class MD5HashType : IUserType {
public SqlType[] SqlTypes {
get { return new[] { new SqlType(DbType.Binary, 16) }; }
}
public Type ReturnedType {
get { return typeof(MD5Hash); }
}
public new bool Equals(object x, object y) {
return Object.Equals(x, y);
}
public int GetHashCode(object x) {
return (null == x) ? 0 : x.GetHashCode();
}
public object NullSafeGet(IDataReader rs, string[] names, object owner) {
var val = NHibernateUtil.Binary.NullSafeGet(rs, names[0]);
return (null == val || DBNull.Value == val) ? MD5Hash.Empty : new MD5Hash((byte[])val);
}
public void NullSafeSet(IDbCommand cmd, object value, int index) {
var val = (MD5Hash.Empty == ((MD5Hash)value)) ? null : ((MD5Hash)value).ToByteArray();
NHibernateUtil.Binary.NullSafeSet(cmd, val, index);
}
public object DeepCopy(object value) {
return value;
}
public bool IsMutable {
get { return false; }
}
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;
}
}
MD5Hash IUserType'ın kodu, sorunuzu yanıtlarken çok yardımcı olacaktır. –
Ayrıca, PK olarak bir karma, korkunç bir fikirdir. –
Oyun kodunu ekledim ama yardımcı olduğundan emin değilim. NHibernate koduyla adım attı ve NullSafeGet'in null değerine ve no'lu parametrelere karşı test ettiğini ve "kaydedilmemiş değer" için sağladığım değere karşı test ettiğini anladım. –
Faron