IBatis.Net 中的数据类型转换

  • Post author:
  • Post category:其他



关键词:

IBatis.NET Access mdb cast typeHandler

类型转换


这两天被一个问题折磨得死去活来,终于解决了,写下来以备参考:



问题是这样的:



我在项目中使用了

IBatis.Net

,数据库使用的是

MS Access

。因为

Access

数据库没有

float



double

类型,只有

Currency

类型可以用作浮点数。所以我定义了类似如下的对象,表,以及

SQL

语句:

1.

对象



public


class

Mark


{



public


string

Subject{…}



public


int

Year{…}



public


double

Point{…}


}



2.

数据库

Mark

Subject       Text

Year           Number

Point          Currency

3.SQL statement



<


statements


>



<


select




id


=”Query”




parameterMap


=”pMarkMap”




resultMap


=”rMarkMap”>


Select Subject, Year, Point


From Mark



<


dynamic




prepend




=”Where”>



<


isNotNull




prepend


=”



AND







property


=”Subject”>


Subject = #Subject#



</


isNotNull


>



<


isNotNull




prepend


=”



AND







property


=”Year”>


Year = #Year#



</


isNotNull


>



</


dynamic


>



</


select


>



</


statements


>


4.

查询数据库


Mark mark =

new

Mark();


mark.Year = 2005;


ISqlMapper mapper = Mapper.Instance();


Object obj = mapper.QueryForObject(“Mark.Query”, mark);


mark = obj

as

Mark;


ArrayList list =

new

ArrayList();


list.Add(obj);



Grid.DataSource = list;



结果抛出异常:


“Specified cast is not valid.”


这个问题困扰了我两天,最后才发现两个解决办法:



1.




将对象中的


Point

属性的类型改成


decimal.


这种方法固然简单,可是在数据库中使用

Currency

乃不得已,在

SQL Server

中却有

Float

类型可以使用,

IBatis

自动支持从

.


NET





double

类型到数据库

Float

类型的转换。所以如果为了

Currency

而使用

decimal,

则后台数据库变成

SQLServer

或是

Oracle

时,在数据库端不得不使用

Decimal/Money

等类型。或者修改程序中的

decimal

定义为

double

类型,这都不是很合理。所以,下面是一个相对复杂一点却合理的解决方法。




注:


IBatis.Net

自动支持的类型转换请参阅

<<DataMapper Developer Guide>> version 1.5.0





Chapter 3.6, 3.7: Supported database types




2.


使用自定义类型转换函数





·


定义类



using


System;


using


IBatisNet.Common;


using


IBatisNet.DataMapper.TypeHandlers;



namespace


TestIBatis


{



public


class

DoubleCurrencyTypeHandler :


IBatisNet.DataMapper.TypeHandlers.ITypeHandlerCallback


{


#region


ITypeHandlerCallback Members



//

此类型的

null





public


object

NullValue


{



get


{



return


null

;


}


}




public


object

ValueOf(

string

s)


{



//

这个函数用于将

nullValue

值翻译成要比较的

null





//

如果没有,则推荐返回字符串

s



return

s;


}




public


object

GetResult(IResultGetter getter)


{



//

用于将从数据库读取的值转换成

.



NET


中的值



//

这里我们知道

Currency

可以转成

decimal

类型,


//

再用显示转换将

decimal

转换成

double



decimal

v1 = Convert.ToDecimal(getter.Value);



double

v2 = (

double

)v1;



return

v2;


}




public


void

SetParameter(IParameterSetter setter,

object

parameter)


{



// TODO:



.



NET


中的


double

型转换成

decimal

,再转换成

Currency



decimal

v1 = Convert.ToDecimal(parameter);


setter.Value = v1;


}


#endregion


}



}




·




定义


SQL

中的

parameterMap



resultMap





SqlMap.config

中加入下面的语句



<


alias


>



<


typeAlias




alias


=”DoubleCurrency”




type


=”TestIBatis.DoubleCurrencyTypeHandler, TestIBatis”




/>



</


alias


>




<


typeHandlers


>



<


typeHandler




type


=”double”




dbType


=”Currency”




callback


=”DoubleCurrency”




/>



</


typeHandlers


>






SQL statement

所在的

Mark.xml

文件里加上如下语句




<


alias


>



<


typeAlias




alias


=”Mark”




type


=”TestIBatis.Mark, TestIBatis”




/>



</


alias


>






<


parameterMaps


>



<


parameterMap




id


=”pMarkMap”




class


=”Mark”>



<


parameter




property


=”Subject”




column


=”Subject”




/>



<


parameter




property


=”Year”




column


=”Year”




type


=”Int32″




dbType


=”Integer”




/>



<


parameter




property


=”Point”




column


=”Point”




type


=”double”




dbType


=”Currency”




/>



</


parameterMap


>



</


parameterMaps


>




<


resultMaps


>



<


resultMap




id


=”rMarkMap”




class


=”Mark”>



<


result




property


=”Subject”




column


=”Subject”




/>



<


result




property


=”Year”




column


=”Year”




type


=”Int32″




dbType


=”Integer”




/>



<


result




property


=”Point”




column


=”Point”




type


=”double”




dbType


=”Currency”




/>



</


resultMap


>



</


resultMaps


>




<


statements


>



<


select




id


=”Query”




parameterMap


=”pMarkMap”




resultMap


=”rMarkMap”>


Select Subject, Year, Point


From Mark



<


dynamic




prepend




=”Where”>



<


isNotNull




prepend


=”



AND







property


=”Subject”>


Subject = #Subject#



</


isNotNull


>



<


isNotNull




prepend


=”



AND







property


=”Year”>


Year = #Year#



</


isNotNull


>



</


dynamic


>



</


select


>



</


statements


>



运行程序,一切正常




注:关于自定义类型转换,请参阅


<<DataMapper Developer Guide>> version 1.5.0





Chapter 3.5.5





Custom Type Handlers