我正在使用Fluent NHibernate映射到Oracle数据库表。
该表有一个代表日期的数字列。数字表示刻度数,因此转换非常简单。我无法将类型更改为Oracle日期类型,因为其他应用程序使用相同的数据库。
我想在我的模型类中使用DateTime属性:
public virtual DateTime Time { get; set; }
并将其映射到刻度线列。我试着用
.CustomType(typeof(long))
但它没有那么好用,NHibernate抛出了System.InvalidCastException(我的猜测是在Int64和DateTime之间存在问题)。
我必须实现IUserType,还是有更简单的方法?
答案 0 :(得分:2)
也许IUserType会有所帮助,但我自己从未这样做过。
你可以做什么,作为一种解决方法是这样的:
在班级中创建2个属性:
一个拥有TimeSpan的私有财产
private TimeSpan Ts
{
get;
set;
}
public DateTime TheDate
{
get
{
return new DateTime (Ts.Ticks);
}
set
{
Ts = new TimeSpan (value.Ticks);
}
}
将NHibernate映射中的私有属性映射到数据库中的特定列,以便NHibernate可以保存和检索值。 公共DateTime属性只访问TimeSpan属性,并将Timespan转换为其getter中的DateTime,并在其setter中设置Timespan(将datetime转换为timespan)。
此变通办法的唯一缺点是您无法在查询中使用DateTime属性。 (除非您也映射此属性,并指定NHibernate不应保存此属性,但我不确定这是否可行)。
答案 1 :(得分:2)
就像后续行动一样,这是一个处理此问题的UserType示例:
public class DateTimeToTicksUserType : IUserType
{
public object Assemble(object cached, object owner)
{
return cached;
}
public object DeepCopy(object value)
{
return value;
}
public object Disassemble(object value)
{
return value;
}
public new bool Equals(object x, object y)
{
if (x == null) return false;
return x.Equals(y);
}
public int GetHashCode(object x)
{
return x.GetHashCode();
}
public bool IsMutable
{
get { return false; }
}
public object NullSafeGet(IDataReader rs, string[] names, object owner)
{
object value = NHibernateUtil.Int64.NullSafeGet(rs, names);
if (value == null)
{
return null;
}
return new DateTime((long) value);
}
public void NullSafeSet(IDbCommand cmd, object value, int index)
{
if (value == null)
{
NHibernateUtil.Int64.NullSafeSet(cmd, null, index);
return;
}
value = ((DateTime) value).Ticks;
NHibernateUtil.Int64.NullSafeSet(cmd, value, index);
}
public object Replace(object original, object target, object owner)
{
return original;
}
public Type ReturnedType
{
get { return typeof (DateTime); }
}
public SqlType[] SqlTypes
{
get { return new[] {new SqlType(DbType.Int64)}; }
}
}
答案 2 :(得分:0)
最终我实现了一个IUserType。借助我在网上找到的一些例子,它非常简单。