我有一個存儲日期傳統DB這意味着無日期9999-21-31, 列Till_Date
是DateTime類型not-null="true"
的。NHibernate的IUserType轉換爲空的日期時間到DB不是空值
在應用程序中,我想構建持久化類,它表示無日期爲空, 因此,我在C#// public DateTime中使用了可空的DateTime? TillDate {get;組; }
我創建IUserType,知道的實體空值轉換爲DB 9999-12-31
但似乎NHibernate的不叫SafeNullGet,SafeNullSet我IUserType 當實體值爲空,並且報告null用於非空列。
我試圖通過映射列不空=「假」 (只更改了映射文件,而不是DB) ,但它仍然沒有幫助繞過它,只是現在它試圖插入將空值賦給數據庫並獲取ADOException。
任何知識,如果NHibernate不支持IUseType將空值轉換爲非空值?
//在需要修復之前執行!!!
public class NullableDateTimeToNotNullUserType : IUserType
{
private static readonly DateTime MaxDate = new DateTime(9999, 12, 31);
public new bool Equals(object x, object y)
{ //This didn't work as well
if (ReferenceEquals(x, y)) return true; //if(x == null && y == null) return false;
if (x == null || y == null) return false;
return x.Equals(y);
}
public int GetHashCode(object x)
{
return x == null ? 0 : x.GetHashCode();
}
public object NullSafeGet(IDataReader rs, string[] names, object owner)
{
var value = rs.GetDateTime(rs.GetOrdinal(names[0]));
return (value == MaxDate)? null : value;
}
public void NullSafeSet(IDbCommand cmd, object value, int index)
{
var dateValue = (DateTime?)value;
var dbValue = (dateValue.HasValue) ? dateValue.Value : MaxDate;
((IDataParameter)cmd.Parameters[index]).Value = dbValue;
}
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 SqlType[] SqlTypes
{
get { return new[] { NHibernateUtil.DateTime.SqlType }; }
}
public Type ReturnedType
{
get { return typeof(DateTime?); }
}
public bool IsMutable
{
get { return false; }
}
}
}
//最終實施與修復。
//Make the column mapping in hbm.xml not-null="false" even if in DB null not allowed.
//Make sure the class mapping in xml doesn't have dynamic-insert="true"
public class NullableDateTimeToNotNullUserType : IUserType
{
private static readonly DateTime MaxDate = new DateTime(9999, 12, 31);
public new bool Equals(object x, object y)
{ //This didn't work as well
if (ReferenceEquals(x, y)) return true; //if(x == null && y == null) return false;
if (x == null || y == null) return false;
return x.Equals(y);
}
public int GetHashCode(object x)
{
return x == null ? 0 : x.GetHashCode();
}
public object NullSafeGet(IDataReader rs, string[] names, object owner)
{
var value = NHibernateUtil.Date.NullSafeGet(rs, names[0]);
return (value == MaxDate)? default(DateTime?) : value;
}
public void NullSafeSet(IDbCommand cmd, object value, int index)
{
var dateValue = (DateTime?)value;
var dbValue = (dateValue.HasValue) ? dateValue.Value : MaxDate;
NHibernateUtil.Date.NullSafeSet(cmd, valueToSet, index);
}
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 SqlType[] SqlTypes
{
get { return new[] { NHibernateUtil.DateTime.SqlType }; }
}
public Type ReturnedType
{
get { return typeof(DateTime?); }
}
public bool IsMutable
{
get { return false; }
}
}
}
使用調試我看到對等值的調用傳遞兩個比較值爲null。 我試過2個版本的Equals的,就認爲: 1日返回true,如果比較的值都爲空 2日返回false,如果比較的值都爲空 請參閱添加的代碼執行 TNX – barakbbn 2010-03-25 21:12:52
我根據你的代碼調整的事情(添加顯式轉換在NullSafeGet) 它的工作原理,除了在下列情況下, 如果在DB的日期是不是最大(例如,2010-01-01) ,我取的實體,更改日期爲空並保存更改,然後 它會調用返回false的Equals(2010-01-01,null), 但不調用NullSafeSet並拋出以下異常: NHibernate.PropertyVa lueException:非空屬性引用空值或瞬態值。 然後,我在hbm.xml中將映射更改爲not-null =「false」,並且它在這次調用了NullSafeSet。 感謝您的幫助 – barakbbn 2010-03-26 15:52:09
我有點驚訝,非空設置會影響到這一點,我認爲這隻適用於模式生成。如果有幫助,請注意並接受答案。 – 2010-03-26 16:01:34