我有一个Oracle数据库,其中一个字段是日期范围字段。它基本上只是作为VARCHAR(40)存储在数据库中,格式为YYYY / MM / DD-YYYY / MM / DD。我想将它在nHibernate中映射到我创建的自定义类
public class DateTimeRange
{
public DateTimeRange(DateTime fromTime, DateTime toTime)
{
FromTime = fromTime;
ToTime = toTime;
}
public override string ToString()
{
return String.Format("{0} to {1}", FromTime.ToString("HH:mm:ss"), ToTime.ToString("HH:mm:ss"));
}
public DateTime FromTime { get; set; }
public DateTime ToTime { get; set; }
}
如何映射到这样的自定义类?
答案 0 :(得分:18)
您需要实现自己的IUserType。
有关详细信息,请参阅此blog post。如果博客消失,我还会粘贴下面的相关部分。
在NHibernate中,自定义映射类型是从IUserType或ICompositeUserType接口派生的类。这些接口包含几个必须实现的方法,但出于我们的目的,我们将重点关注其中的两个。考虑以下。
public class TypeClassUserType : IUserType
{
object IUserType.NullSafeGet(IDataReader rs,
string[] names,
object owner) {
string name = NHibernateUtil.String.NullSafeGet(rs,
names[0]) as string;
TypeClassFactory factory = new TypeClassFactory();
TypeClass typeobj = factory.GetTypeClass(name);
return typeobj;
}
void IUserType.NullSafeSet(IDbCommand cmd,
object value,
int index) {
string name = ((TypeClass)value).Name;
NHibernateUtil.String.NullSafeSet(cmd, name, index);
}
}
创建此类后,我现在可以将ActualClass和TypeClass之间的关联显式映射为ActualClass映射的简单属性。
<property
name="Type"
column="TypeName"
type="Samples.NHibernate.DataAccess.TypeClassUserType,
Samples.NHibernate.DataAccess" />
由于NHibernate正在保存ActualType的实例,它将加载并创建TypeClassUserType的新实例并调用NullSafeSet方法。从方法体中可以看出,我只是从映射属性中提取名称(作为value参数传入),并将提取的名称设置为要在数据库中设置的参数的值。最终结果是,尽管ActualClass的Type属性是域模型中的TypeClass,但只有TypeClass对象的Name属性存储在数据库中。反过来也是如此。当NHibernate从数据库加载ActualType的实例并找到我的自定义映射类型的属性时,它会加载我的自定义类型并调用NullSafeGet方法。如您所见,我的方法从返回的数据中获取名称,调用我的flyweight工厂以获取TypeClass的正确实例,然后实际返回该实例。类型解析过程透明地发生在我的数据访问类中(甚至NHibernate本身也是如此)。