代码改变世界

Subsonic查询中奇怪的数据丢失问题

2010-11-09 17:43  MichaelYin  阅读(391)  评论(1编辑  收藏  举报

昨天在项目中遇到了一个很奇怪的问题,用Subsonic查询出来的对象中部分字段值出现了丢失,比如我写这样一个查询语句

ViewIceCalculate objViewIce = new Select().Top("1").From<ViewIceCalculate>().ExecuteSingle<ViewIceCalculate>();

后面的查询跟Sql语句差不多的,返回一个对象,但是从程序Debug中来看的话,有些属性并没有取到值,这个有点奇怪的现象引起了我的兴趣,在网上找了一下,找到了对应的源码,将SubSonic Project加载到我实验的Console的Project中去,查询中所调用的东西都在里面。

然后再Subsonic中去看了一下,由于是从new Select开始的查询,所以先看看Select这个类把,发现Select这个类继承自SqlQuery,又跑到SqlQuery这个类中一窥究竟。在SqlQuery我没有看到Top,不过发现了一个名叫From的方法,看来有戏啊,继续发现之旅。。。看看这里里面有没有ExecuteSingle,结果还真有,一路找寻,找到了一个叫BuildSqlStatement的方法,看样子Sql语句的拼凑是在这里完成的,果断设断点,然后启动调试,到这里将生成的Sql语句贴到SQl中运行,数据是可以全部查出来的,那么问题就不出在这里了。。

数据查寻出来后返回的是一个IDataReader的接口,ExecuteSingle中还有另外一个叫做BuildTypedResult的方法,在代码中找到方法的代码,然后设了断点,然后。。。我知道悲剧为什么发生了。。。。

先上代码吧。

 PropertyInfo[] cachedProps = new PropertyInfo[rdr.FieldCount];
                for (int i = 0; i < rdr.FieldCount; i++)
                    cachedProps[i] = iType.GetProperty(rdr.GetName(i), BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);

rdr是返回的IDataReader的对象,先根据字段数初始化一个PropertyInfo数组,然后后面一段,是根据DataReader中的Name来或获取属性。执行到这里的时候属性数组中有些属性竟然丢失了,我找到生成的对应的类的代码看了下,发现这其实是一个不起眼的误会。。。。

在数据库的表和字段的命名中,有的人是喜欢加前缀的,而一般前缀加了之后后面的字段就跟在一个下划线后面,比如Sys_User标识系统模块中的用户表,这样是没问题,但是Subsonic中生成的代码默认情况下是将下划线移除了的,所以表名和字段名是SysUser这样,在类中的属性名子成了这样,但是如果Datareader中的名字是Sys_User时,获取属性获取不到就是很自然的事情了。。。

发现问题所在我在Subsonic的代码生成器中看了下,发现生成器Substage中Global下有个removeunderscore这个选项,默认是true,改成False生成代码里就会保留下划线。。其实解决方法很简单,但是知道了这其中的原理对我来说或许更显宝贵。。。。