zoukankan      html  css  js  c++  java
  • 疑是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,
    不是知是否在其他地方还有处理。
    在使用别人的代码时,要多看看,多了解,多做测试。
    如果说的不对的地方,请多指出。

  • 相关阅读:
    JS正则表达式
    TortoiseGit 中文汉化
    java之 Mybatis框架
    正向代理和反向代理
    Java基础之 多线程
    python库参考学习网址
    postman进行https接口测试所遇到的ssl证书问题,参考别人方法
    hbase单机搭建
    搭建单机版伪分布zookeeper集群
    搭建hadoop单机版
  • 原文地址:https://www.cnblogs.com/chillsrc/p/353864.html
Copyright © 2011-2022 走看看