我有一个存储日期传统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