2010-03-25 2 views
3

날짜가 9999-21-31, 인 날짜를 저장하는 레거시 DB가 있습니다. Till_Date 열은 DateTime not-null="true"입니다.NHibernate IUserType nullable DateTime을 DB가 아닌 값으로 변환합니다.

응용 프로그램에서 null이 아닌 날짜를 나타내는 지속 된 클래스를 작성하려고합니다. 그래서 C# // public DateTime에 Nullable DateTime을 사용 했습니까? TillDate {get; 세트; }

나는 9999-12-31

을 dB로 엔티티 널 (null) 값을 변환 할 알고 있지만 엔티티 값이 null 인 경우 NHibernate에 내 IUserType 에 SafeNullGet, SafeNullSet를 호출하지 않는 것 같다 IUserType을 만들어

, null이 아닌 열에 null이 사용되었다고보고합니다.

나는 NULL이 아닌 "false" (DB가 아닌 매핑 ​​파일 만 변경됨) 으로 열을 매핑하여 우회하려고했으나 여전히 도움이되지 않으며 삽입 만 시도합니다 DB 에의 null 치를 취득 해, 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; } 
     } 
    } 
} 

답변

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

디버깅을 사용하면 비교 된 값 모두에 대해 equals에 대한 호출이 null을 전달한다는 것을 알 수 있습니다. 는 그에 대해 같음 2 버전을 시도 : 비교 값이 비교 값이 null의 경우는 null 2 반환 거짓 경우는 true 1 수익을 난 당신의 코드에 따라 일을 조정 TNX – barakbbn

+0

추가 코드 구현 (추가 명시 적 캐스팅을 참조하십시오 다음 시나리오를 제외하고 작동 날짜가 최대 (예 : 2010-01-01) 이 아니고 엔터티를 가져 와서 날짜를 null로 변경하고 변경 사항을 저장하면 그 다음 false를 반환하는 Equals (2010-01-01, null)를 호출하지만 NullSafeSet을 호출하지 않고 다음 예외를 throw합니다. NHibernate.PropertyVa lueException : not-null 프로퍼티가 null 또는 일시적인 값을 참조한다 그런 다음 매핑을 hbm.xml에서 not-null = "false"로 변경했으며이 시간에 NullSafeSet이 호출되었습니다. 도움을 주셔서 감사합니다. – barakbbn

+0

null이 아닌 설정이이 작업에 영향을 미친다는 사실에 조금 놀랐습니다. 스키마 생성에만 해당되는 것으로 생각했습니다. 그것이 도움이된다면 답을 upvote하고 동의하십시오. –