Nibernate Mapeamento para tipos personalizados
-
04-07-2019 - |
Pergunta
Eu tenho um banco de dados Oracle e um dos campos é um campo de intervalo de data. É basicamente armazenado apenas no banco de dados como um varchar (40) no formato yyyy/mm/dd-yyyy/mm/dd. Eu quero mapeá -lo em Nibernate para uma aula personalizada que criei assim
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; }
}
Como posso mapear para classes personalizadas como essa?
Solução
Você precisa implementar seu próprio iUserType.
Veja isso Postagem do blog para detalhes. Também colarei a seção relevante abaixo, caso o blog desapareça.
No Nibernate, um tipo de mapeamento personalizado é uma classe que deriva das interfaces IUSERTYPE ou ICOMOPOSTUSERTYPE. Essas interfaces contêm vários métodos que devem ser implementados, mas para nossos propósitos aqui, vamos nos concentrar em 2 deles. Considere o seguinte.
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);
}
}
Tendo criado essa classe, agora posso mapear explicitamente a associação entre o RealClass e o TypeClass como uma propriedade simples no mapeamento real da Class.
<property
name="Type"
column="TypeName"
type="Samples.NHibernate.DataAccess.TypeClassUserType,
Samples.NHibernate.DataAccess" />
Como o Nhibernate está no processo de salvar uma instância do RealType, ele carregará e criará uma nova instância do typeClassUserType e chamará o método NullSafeset. Como você pode ver no corpo do método, estou simplesmente extraindo o nome da propriedade mapeada (passada como parâmetro de valor) e definindo o nome extraído como o valor do parâmetro a ser definido no banco de dados. O resultado líquido é que, embora o tipo de propriedade do RealClass seja o TypeClass no modelo de domínio, apenas a propriedade Nome do objeto TypeClass é armazenada no banco de dados. O inverso também é verdadeiro. Quando o Nhibernate está carregando uma instância do RealType do banco de dados e as localização de uma propriedade do meu tipo de mapeamento personalizado, ele carrega meu tipo personalizado e chama o método NullSafeget. Como você pode ver, meu método recebe o nome dos dados retornados, chama minha fábrica de peso mosca para obter a instância correta do TypeClass e, na verdade, retorna essa instância. O processo de resolução do tipo acontece de forma transparente às minhas classes de acesso a dados (e até mesmo para se atingir para esse assunto).