您的位置:首页 > 其它

疑是Microsoft Enterprise Library June 2005的一个小bug

2006-03-20 11:14 459 查看
大家在用水晶报表做报表时,是否则需要给水晶报表提供一些参数,这些参数是用户名,密码,数据库,服务器名称(或是IP地址)。
如果把这些参数各自写到web.config中,那么有可能与已有的数据库连接字符串重复。
例如:
一般可能在web.config中这样写
<appSettings>
<!--用于水晶报表的数据库参数传递-->
<add key="Server" value="127.0.0.1" />
<add key="UserID" value="sa" />
<add key="Password" value="sa" />
<add key="DataBase" value="test" />
<!--另外还有一个数据库连接 ,当然这个连接也可以不要,在程序中根据上面的四个参数,自己生成。-->
<add key="ConnectionString" value="data source=127.0.0.1;initial catalog=test;User ID=sa;Password=sa;persist security info=False;packet size=4096"/>
</appSettings>
那么还有没有其他方法呢?

我记得当初使用Microsoft Enterprise Library June 2005时,它的data子模块中有username与password这两个属性。于是我把Microsoft Enterprise Library June 2005的源代码找了出来,仔细看了看,原来关键在SR与ConnectionString两个类。
首先我直接拷贝了SR与ConnectionString这两个类的源代码,放入到自己的data处理类中,经过测试,username与password取出来的竟是空值?我百思不得其解。
(注:拷贝SR类是,还要拷贝两个文件,SR.resx与SR.strings)

接着,自己做了一个Dome,专门来测试这些相关类,一开始都没有问题,程序运行到username在数据库字符串连接中的位置索引这个方法时,才发出这个方法中有个bug,请看源码。
通过监视窗口查看,原来lowConnString中的所有字符全部转换为小写了,而tokens中的字符仍然保持原样。
原来的:string[] tokens = tokenString.Split(',')
修改后:string[] tokens = tokenString.ToLower().Split(',')
经过测试,可以得到相应的值了,但是取得结果 :
=sa
=sa
看来程序中还是有错误。我只要sa与sa,不要那个"="


再次修改:
原来:tokenMPos = currentPos + token.Length;
修改后: tokenMPos = currentPos + token.Length+1;
这下最终可以取得sa ,sa 了。

在通过了上面的测试后,自己又给代码添加了server与database两个属性。
这下通过ConnectionString类就可以根据数据库连接字符串就可以取得相应和值了。


1.资源文件中:

[strings]
UserName=User id,uid
Password=Password,pwd
FactoryName = Database

2.原来的DataBase中的得到用户名与密码的方式
public abstract class Database : ConfigurationProvider
{
--此处得到用户名与密码
private static readonly string VALID_USER_ID_TOKENS = SR.UserName; //SR.UserName得到的资源文件中的UserName
private static readonly string VALID_PASSWORD_TOKENS = SR.Password;
//其他省略
protected string ConnectionString
{
get
{
string s = ConnectionStringBuilder.Build(DatabaseProviderData.ConnectionStringData);
ConnectionString connectionString = new ConnectionString(s, VALID_USER_ID_TOKENS, VALID_PASSWORD_TOKENS);
return connectionString.ToString();
}
}
}

3. ConnectionString类
internal class ConnectionString
{
private const char CONNSTRING_DELIM = ';';
private string connectionString;
private string connectionStringWithoutCredentials;
private string userIdTokens;
private string passwordTokens;

public ConnectionString(string connectionString, string userIdTokens, string passwordTokens)
{
this.connectionString = connectionString;
this.userIdTokens = userIdTokens;
this.passwordTokens = passwordTokens;

this.connectionStringWithoutCredentials = RemoveCredentials(this.connectionString);
}

/// <devdoc>
/// Database username for the connection string
/// </devdoc>
public string UserName
{
get
{
string lowConnString = connectionString.ToLower(CultureInfo.CurrentCulture);
int uidPos;
int uidMPos;

GetTokenPositions(userIdTokens, out uidPos, out uidMPos);
if (0 <= uidPos)
{
// found a user id, so pull out the value
int uidEPos = lowConnString.IndexOf(CONNSTRING_DELIM, uidMPos);
return connectionString.Substring(uidMPos, uidEPos - uidMPos);
}
else
{
return String.Empty;
}
}
//省略
}
//其他省略
private void GetTokenPositions(string tokenString, out int tokenPos, out int tokenMPos)
{
//此处是需要提取的名称的分隔。但没有进行小写转换
string[] tokens = tokenString.Split(',');
int currentPos = -1;
int previousPos = -1;
//把得当前的数据库字符串连接,进行小写转换
string lowConnString = connectionString.ToLower(CultureInfo.CurrentCulture);

//initialze output parameter
tokenPos = -1;
tokenMPos = -1;
foreach (string token in tokens)
{
//获取在此实例中的第一个匹配项的索引
//但是由于tokens没有进行小写转换,很有可能是得不到第索引值的。
currentPos = lowConnString.IndexOf(token);
if (currentPos > previousPos)
{
tokenPos = currentPos;
tokenMPos = currentPos + token.Length;
previousPos = currentPos;
}
}

}

}

4.我的修改后的ConnectionString类
//我只修改了其中的GetTokenPositions方法,基他都没改。
private void GetTokenPositions(string tokenString, out int tokenPos, out int tokenMPos)
{
//进行小写转换
string[] tokens = tokenString.ToLower().Split(',');
int currentPos = -1;
int previousPos = -1;
string lowConnString = connectionString.ToLower(CultureInfo.CurrentCulture);

//initialze output parameter
tokenPos = -1;
tokenMPos = -1;
foreach (string token in tokens)
{
currentPos = lowConnString.IndexOf(token);
if (currentPos > previousPos)
{
tokenPos = currentPos;
//在得到相应索引值后+1,把" = "这个字符也算进去。
tokenMPos = currentPos + token.Length+1;
previousPos = currentPos;
}
}
}

总结:首先要感谢Microsoft,有了这个开源的东东。到此,我自己的ConnectionString类完成了。
我没有完正的使用过Microsoft Enterprise Library June 2005中的所有功能,我也没有使用过Microsoft Enterprise Library June 2005中的username与password的属性,所以是否是bug,我不敢确定。但是我把它拷贝到自己的处理类中之后,就出现了这样的bug,
不是知是否在其他地方还有处理。
在使用别人的代码时,要多看看,多了解,多做测试。
如果说的不对的地方,请多指出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐