VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > C#教程 >
  • 疑是Microsoft Enterprise Library June 2005的一个小bug

 大家在用水晶报表做报表时,是否则需要给水晶报表提供一些参数,这些参数是用户名,密码,数据库,服务器名称(或是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,
不是知是否在其他地方还有处理。
在使用别人的代码时,要多看看,多了解,多做测试。
如果说的不对的地方,请多指出。



出处:https://www.cnblogs.com/chillsrc/archive/2006/03/20/353864.html


相关教程