以前提到的一个项目使用到了ASP.NET 1.1+Firebird embedded数据库,数据库使用了2.0.1,数据连接适配器使用了Firebird Net Provider 1.7 RC3。
FbClient.isc_attach_database(
statusVector,
(short)database.Length, //问题在这
database,
ref
dbHandle,
(short
)dpb.Length,
dpb.ToArray());
//获取字符串真实长度(中文为2字节,英文为1字节)
private int getTrueLength(string
str)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
int lenTotal = 0;
int n = str.Length;
string strWord = "";
int asc;
for(int i=0;i<n;i++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
strWord = str.Substring(i,1);
asc = Convert.ToChar(strWord);
if ( asc < 0 || asc > 127 )
lenTotal = lenTotal + 2;
else
lenTotal = lenTotal + 1;
}
return lenTotal;
}
FbClient.isc_attach_database(
statusVector,
(short
)getTrueLength(database),
database,
ref
dbHandle,
(short
)dpb.Length,
dpb.ToArray());
但最近将程序加入嵌入式Web服务器之后,却出现了无法连接数据库的问题,经过排查,发现,以前使用IIS做Web服务时,路径中没有中文;而当使用中文路径存放整个执行程序时,就会无法连接数据库的问题,且只有使用嵌入式服务器时才会出现。
为了缩小问题的排查范围,我将同一项目组的一个Delphi项目配置为嵌入式数据库,并放入中文目录中,测试没有问题,于是可以基本排除嵌入式数据库版本问题。于是我到网上搜索Firebird Net Provider的相关内容,发现,确实有人提到了此问题,但不知道是不是被解决了。与此同时,我发现了Firebird Net Provider 1.7 RC4,眼前一亮,说不定,这个版本已经解决了整个问题。
一阵折腾,拿下了最新的RC4,安装、运行…心又凉了半截――外甥打灯笼,照旧。看了看发布时间,2006年,看来,还真是没人管这事。不过值得庆幸的是,这次的错误提示比较精确了,提示是那个路径找不到…等等!数据库文件路径后面咋少了仨字符?难道是因为中文的存在,被截掉了?希望再次燃烧起来,因为,刚刚下载驱动的时候,也看到了源码的下载链接。
看来这次得自己动手丰衣足食了。又一阵折腾,下载下来这个工程的源码,解压、编…咦?貌似是NANT的工程,看来只能用文本编辑器来修改代码。不过还好,平时用的东西杂,家什设备齐全,逐步跟踪,最终发现了问题所在:
在将连接字符串connectionString解析成database字符串时,使用了length属性来返回字符串的长度。将其传给数据库引擎的相关函数。但.NET中这个length默认是字长度,而嵌入式Firebird引擎是非托管代码,需要的是字节长度,由此造成了字符串被截断的错误。
经过跟踪发现,具体的BUG在FirebirdSql.Data.Embedded/FesDatabase.cs文件中,FesDatabase类的Attach函数,将database字符串以及其长度传递给嵌入式数据库的非托管dll,其关键代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
代码中, (short)database.Length用来计算字符串的长度,而.NET默认环境将中英文全部视为Unicode编码,因此该属性得到的是字符串的字长,而并非字节长度。但.NET并没有直接提供获取字节长度的代码,只能手动创建函数:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/1327ab569c1ae82736693a50b8e33378.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
并将有问题代码改为:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
保存、编译、运行,问题解决。
注意事项:
1、 对于计算字节长度的函数,网上还有另一种解决方法,就是使用GB2312编码来转换,但由于编码的针对性,这个方法会有潜在的错误,不建议使用。
2、 如果你的驱动文件是安装版本,请在替换原有文件之前,删除系统assembly目录中的索引,以免系统缓存的存在使修改无效。
后记:已编译完成的DLL文件我已经放在:
http://www.qihangsoft.net/download/Firebird_NET_Provider_1.7_fix_nose.rar
,你可以免费下载使用。