C# Oracle间隔日到第二个数据类型的NHibernate映射
与其说是一个问题,不如说是我向我的一位同事提出的一个问题。我们的一个对象上有一个必须持久化的属性。是的,您可以从对象的开始和结束属性推断值,但DBA坚持认为该值保存在数据库表中 因此,DBA选择用来保存该值的Oracle数据类型是间隔日(2)到秒(6) Oracle.DataAccess中对应的类型是OracleDbType.invervals,但我还没有找到任何与如何将其映射到NHibernate相关的内容 我们最终得到了这个解决方案C# Oracle间隔日到第二个数据类型的NHibernate映射,c#,.net,oracle,nhibernate,orm,C#,.net,Oracle,Nhibernate,Orm,与其说是一个问题,不如说是我向我的一位同事提出的一个问题。我们的一个对象上有一个必须持久化的属性。是的,您可以从对象的开始和结束属性推断值,但DBA坚持认为该值保存在数据库表中 因此,DBA选择用来保存该值的Oracle数据类型是间隔日(2)到秒(6) Oracle.DataAccess中对应的类型是OracleDbType.invervals,但我还没有找到任何与如何将其映射到NHibernate相关的内容 我们最终得到了这个解决方案 public class SomeTimeSpan
public class SomeTimeSpanTestClass
{
public virtual string TimeSpanTest { get; protected set; }
public virtual TimeSpan ActualTimeSpan
{
get
{
// Need to do some formatting of TimeSpanTest before it can be parsed
return TimeSpan.Parse(TimeSpanTest);
}
set
{
TimeSpanTest = string.Format("{0}{1} {2}:{3}:{4}.{5}",
value.ToString().Contains('-') ? "-" : "+",
value.Days.ToString().Contains('-') ? value.Days.ToString().Substring(1).PadLeft(2, '0') : value.Days.ToString().PadLeft(2, '0'),
value.Hours.ToString().Contains('-') ? value.Hours.ToString().Substring(1).PadLeft(2, '0') : value.Hours.ToString().PadLeft(2, '0'),
value.Minutes.ToString().Contains('-') ? value.Minutes.ToString().Substring(1).PadLeft(2, '0') : value.Minutes.ToString().PadLeft(2, '0'),
value.Seconds.ToString().Contains('-') ? value.Seconds.ToString().Substring(1).PadLeft(2, '0') : value.Seconds.ToString().PadLeft(2, '0'),
value.Milliseconds.ToString().Contains('-') ? value.Milliseconds.ToString().Substring(1).PadLeft(6, '0') : value.Milliseconds.ToString().PadLeft(6, '0')
);
}
}
}
映射为
<property name="TimeSpanTest" column="TIMESPAN_TEST"/>
显然,这段代码并没有以任何方式进行重构,但就本测试而言,它是微不足道的
数据库中的值基本上必须如下所示“+00 01:15:03.000874”。如果值为负数,则字符串开头的-符号也有效。这里需要注意的一点是:当值为负数时,单独查看TimeSpan对象的每个部分时都是负数,因此在Format()方法的每个部分中都有一个不太漂亮的“value.Days.ToString()。Contains('-')”
通过测试,我们能够通过NHibernate将TimeSpan值保存并检索到定义为间隔日(2)到秒(6)的数据库列中
如果有人以前做过更好的方法,我很想知道怎么做
很抱歉没有链接Oracle类型,这是我的第一篇文章,所以我不允许…您也可以使用NH Usertype来映射Timespan属性。那么您就不需要对象中的TimeSpatest和转换代码了。如果需要,我可以发布一个实现。就像我说的,这是我们第一次尝试,如果有更好的方法,我想知道怎么做。谢谢你的回复。我不知道你使用IDataReader和IDbCommand如何与NHibernate交互。我不明白这个问题。如代码所示,NH将其作为参数提供,您只需插入/检索值
public virtual TimeSpan ActualTimeSpan { get; set; }
class TimeSpanUserType : ImmutableUserType
{
public override object NullSafeGet(IDataReader rs, string[] names, object owner)
{
// Need to do some formatting of TimeSpanTest before it can be parsed
return TimeSpan.Parse((string)rs[names[0]]);
}
public override void NullSafeSet(IDbCommand cmd, object value, int index)
{
var timespan = (TimeSpan)value;
var duration = timespan.Duration();
var timeSpanstring = string.Format("{0}{1} {2}:{3}:{4}.{5}",
(timespan.Ticks < 0) ? "-" : "+",
duration.Days.ToString().PadLeft(2, '0'),
duration.Hours.ToString().PadLeft(2, '0'),
duration.Minutes.ToString().PadLeft(2, '0'),
duration.Seconds.ToString().PadLeft(2, '0'),
duration.Milliseconds.ToString().PadLeft(6, '0'));
NHibernateUtil.String.NullSafeSet(cmd, timeSpanstring, index);
}
public override Type ReturnedType
{
get { return typeof(TimeSpan); }
}
public override SqlType[] SqlTypes
{
get { return new[] { SqlTypeFactory.GetString(8) }; }
}
}
<property name="ActualTimeSpan" column="TIMESPAN_TEST" type="TimeSpanUserType"/>
public virtual TimeSpan ActualTimeSpan { get; set; }
class TimeSpanUserType : ImmutableUserType
{
public override object NullSafeGet(IDataReader rs, string[] names, object owner)
{
// Need to do some formatting of TimeSpanTest before it can be parsed
return TimeSpan.Parse((string)rs[names[0]]);
}
public override void NullSafeSet(IDbCommand cmd, object value, int index)
{
var timespan = (TimeSpan)value;
var duration = timespan.Duration();
var timeSpanstring = string.Format("{0}{1} {2}:{3}:{4}.{5}",
(timespan.Ticks < 0) ? "-" : "+",
duration.Days.ToString().PadLeft(2, '0'),
duration.Hours.ToString().PadLeft(2, '0'),
duration.Minutes.ToString().PadLeft(2, '0'),
duration.Seconds.ToString().PadLeft(2, '0'),
duration.Milliseconds.ToString().PadLeft(6, '0'));
NHibernateUtil.String.NullSafeSet(cmd, timeSpanstring, index);
}
public override Type ReturnedType
{
get { return typeof(TimeSpan); }
}
public override SqlType[] SqlTypes
{
get { return new[] { SqlTypeFactory.GetString(8) }; }
}
}
<property name="ActualTimeSpan" column="TIMESPAN_TEST" type="TimeSpanUserType"/>
public abstract class ImmutableUserType : IUserType
{
public new virtual bool Equals(object x, object y)
{
return object.Equals(x, y);
}
public virtual int GetHashCode(object x)
{
return (x == null) ? 0 : x.GetHashCode();
}
public override bool IsMutable
{
get { return false; }
}
public override object DeepCopy(object value)
{
return value;
}
public override object Replace(object original, object target, object owner)
{
return original;
}
public override object Assemble(object cached, object owner)
{
return cached;
}
public override object Disassemble(object value)
{
return value;
}
public abstract object NullSafeGet(System.Data.IDataReader rs, string[] names, object owner);
public abstract void NullSafeSet(System.Data.IDbCommand cmd, object value, int index);
public abstract Type ReturnedType { get; }
public abstract SqlType[] SqlTypes { get; }
}