摩诘

我思故我在 常辨而常新

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  20 随笔 :: 2 文章 :: 344 评论 :: 11 引用

 

关键词:IBatis.NET Access mdb cast typeHandler 类型转换

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


问题是这样的:


我在项目中使用了
IBatis.Net,数据库使用的是 MS Access。因为Access数据库没有floatdouble类型,只有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自动支持从.NETdouble类型到数据库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

posted on 2006-09-01 21:29 sema 阅读(2445) 评论(5)  编辑 收藏 所属分类: 技术研究

评论

影射的应用,到底适合日常的开发吗?
我现在的公司还用不上.
http://www.pakerliu.com
  回复  引用    

#2楼 [楼主] 2006-09-01 23:56 sema      
我觉得挺好,它支持系统对象和数据库访问层的设计分离,同时还使后台数据库的变化对系统设计的影响降到最低,蛮实用的。我一直都在用。不过相信这个问题也是仁者见仁,智者见智,只要自己觉得好用就行了。
  回复  引用  查看    

求DataMapper Developer Guide,麻烦楼主给个下载地址或发到我email

boyxia@tom.com,不胜感激
  回复  引用    

#4楼 [楼主] 2006-09-02 12:48 sema      
@boyxia,
你可以到下面地址去下载官方最新版
http://ibatis.apache.org/dotnetdownloads.cgi
  回复  引用  查看    

我一直在思考映射和快速的代码实现的德合理管理,取得一个最适当的折衷值,摸索中
  回复  引用    


标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2006-09-01 21:34 编辑过


相关链接: