惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

量子位
P
Privacy International News Feed
Security Latest
Security Latest
Spread Privacy
Spread Privacy
NISL@THU
NISL@THU
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
The Last Watchdog
The Last Watchdog
S
Schneier on Security
Engineering at Meta
Engineering at Meta
Google Online Security Blog
Google Online Security Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Know Your Adversary
Know Your Adversary
Cyberwarzone
Cyberwarzone
C
Cyber Attacks, Cyber Crime and Cyber Security
G
GRAHAM CLULEY
A
Arctic Wolf
博客园 - 聂微东
I
Intezer
腾讯CDC
罗磊的独立博客
T
Tailwind CSS Blog
WordPress大学
WordPress大学
宝玉的分享
宝玉的分享
L
Lohrmann on Cybersecurity
人人都是产品经理
人人都是产品经理
C
Cybersecurity and Infrastructure Security Agency CISA
博客园 - 【当耐特】
P
Palo Alto Networks Blog
Simon Willison's Weblog
Simon Willison's Weblog
W
WeLiveSecurity
N
News and Events Feed by Topic
SecWiki News
SecWiki News
S
Security Affairs
T
Threat Research - Cisco Blogs
The GitHub Blog
The GitHub Blog
F
Fortinet All Blogs
T
Troy Hunt's Blog
N
News and Events Feed by Topic
P
Proofpoint News Feed
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
酷 壳 – CoolShell
酷 壳 – CoolShell
M
MIT News - Artificial intelligence
I
InfoQ
Hacker News: Ask HN
Hacker News: Ask HN
T
The Blog of Author Tim Ferriss
Schneier on Security
Schneier on Security
Hacker News - Newest:
Hacker News - Newest: "LLM"
Vercel News
Vercel News
博客园 - 三生石上(FineUI控件)
D
Darknet – Hacking Tools, Hacker News & Cyber Security

博客园 - sema

Netron开发快速上手(二):Netron序列化 发布一个免费开源软件-- PAD流程图绘制软件PADFlowChart Netron源码解读(一):GraphControl画布对象 Netron开发快速上手(一):GraphControl,Shape,Connector和Connection FileSystemWatcher事件多次触发的解决方法 深入浅出之正则表达式(二) 深入浅出之正则表达式(一) 在.NET环境中实现每日构建(Daily Build)--NAnt篇 自动向网页Post信息并提取返回的信息 在C#中利用自动化模型操纵Word VS.NET 2003集成环境插件开发指南(三)----操纵VS开发环境(完结篇) VS.NET 2003集成环境插件开发指南(二)----使用窗口 VS.NET 2003集成环境插件开发指南(一)----操纵菜单 后期写作计划 利用反射解决QueryString和Session中的参数绑定问题 开发Visual Studio风格的用户界面--MagicLibrary使用指南 Log4Net使用指南 一些写英文简历的词汇吧 关于一些大学课程名的中文翻译
IBatis.Net 中的数据类型转换
sema · 2006-09-01 · via 博客园 - sema

关键词: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