У меня есть наследие DB, которые хранят даты, не означает, что нет-даты как 9999-21-31, Колонка Till_Date
имеет тип DateTime not-null="true"
.NHibernate IUserType конвертировать обнуляемым DateTime к БД не-нулевое значение
в приложении Я хочу построить постоянный класс, который представляет собой дату-значение как null, Итак, я использовал nullable DateTime в C# // public DateTime? TillDate {get; задавать; }
Я создал IUserType, который знает, чтобы преобразовать нулевое значение единицы для DB 9999-12-31
, но кажется, что NHibernate не вызывает SafeNullGet, SafeNullSet на моем IUserType когда значение объекта имеет нулевое значение, и сообщается, что значение null используется для столбца not-null.
Я попытался обойти его отображение столбца не-NULL = «ложь» (изменено только файл отображения, а не DB) , но он все еще не помогло, только теперь он пытается вставить нулевое значение для БД и получить ADOException.
Любые знания, если NHibernate не поддерживает IUseType, которые преобразуют значения null в ненулевые значения?
// Выполнение перед выполнением необходимых исправлений !!!
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-го возвращения верно, если сравниваемые значения равны нулю второе возвращение ложным, если сравниваемые значения равны нулю см добавляется реализация кода Тпх – barakbbn
я настроил вещи в соответствии с вашим кодом (добавлен явное приведение в NullSafeGet) работает, за исключением следующего сценария: , если в БД дата не является максимальной (например, 2010-01-01) , и я получаю сущность, меняю дату на нуль и сохраняю изменения, , затем он вызывает Equals (2010-01-01, null), которые возвращают false, , но не вызывает NullSafeSet и исключает: NHibernate.PropertyVa Свойство lueException: not-null ссылается на значение null или переходное значение. Затем я изменил отображение на not-null = "false" в hbm.xml, и он работал на этот раз, когда был вызван NullSafeSet. Спасибо за помощь – barakbbn
Я немного удивлен, что это не-нулевая настройка влияет на это, я думал, что это было только для генерации схемы. Пожалуйста, поддержите и примите ответ, если это поможет. –