2010-03-25 1 views
3

У меня есть наследие 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; } 
     } 
    } 
} 

ответ

1

Проблема, скорее всего, в вашей реализации Equals. NHibernate использует Equals, чтобы определить, нужно ли ему получить или установить значение. Пожалуйста, опубликуйте свою реализацию IUserType.

Редактировать: Хорошо, я думаю, что вижу проблему. Попробуйте следующее:

public object NullSafeGet(IDataReader rs, string[] names, object owner) 
{ 
    var value = NHibernateUtil.Date.NullSafeGet(rs, 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; 
    NHibernateUtil.Date.NullSafeSet(cmd, valueToSet, index); 
} 

NullSafeGet также может указывать возвращаемое значение как DateTime ?. Ваша реализация Equals выглядит правильно.

+0

используя отладку, я вижу, что вызов равным принимает значение null для обоих сравниваемых значений. Я попробовал 2 версии Equals, относительно этого: 1-го возвращения верно, если сравниваемые значения равны нулю второе возвращение ложным, если сравниваемые значения равны нулю см добавляется реализация кода Тпх – barakbbn

+0

я настроил вещи в соответствии с вашим кодом (добавлен явное приведение в NullSafeGet) работает, за исключением следующего сценария: , если в БД дата не является максимальной (например, 2010-01-01) , и я получаю сущность, меняю дату на нуль и сохраняю изменения, , затем он вызывает Equals (2010-01-01, null), которые возвращают false, , но не вызывает NullSafeSet и исключает: NHibernate.PropertyVa Свойство lueException: not-null ссылается на значение null или переходное значение. Затем я изменил отображение на not-null = "false" в hbm.xml, и он работал на этот раз, когда был вызван NullSafeSet. Спасибо за помощь – barakbbn

+0

Я немного удивлен, что это не-нулевая настройка влияет на это, я думал, что это было только для генерации схемы. Пожалуйста, поддержите и примите ответ, если это поможет. –

Смежные вопросы