zoukankan      html  css  js  c++  java
  • C#中,数据交互层参数替代方案(三)

    在以前的2篇文章中,个人突发奇想的仿效Java中,以?替代参数,然而在应对参数重复的情况下,需要重复填写参数,实在是挺麻烦的。

    因为最近在学习和使用NHibernate,对于Hql中使用[:参数名]的方式可以解决重复参数的问题。

    因为在参数键值传递的时候使用的是Hashtable,因此我们需要通过正则匹配【":\w+"】,并截取得到对应的键,获取对应的值。

    代码如下:

     1 Regex regMark = new Regex(@":\w+");
    2 sql = regMark.Replace(sql, s =>
    3 {
    4 string mark = s.Value.Substring(1), paramName = string.Empty;
    5 if (columns.ContainsKey(mark))
    6 {
    7 //获取参数名并创建DbParameter
    8 }
    9 else
    10 {
    11 throw new NullReferenceException("不存在对应的标记键值!");
    12 }
    13 return paramName;
    14 });

    因为参数可能会出现重复,出现重复的时候,通过对应的[:参数名],需要获取DbParameter以及Sql中的@参数名,并且我们通过Hashtable传入的值可能是数组,因此我选择使用泛型字典IDictionary<string, IDictionary<string, DbParameter>>存储。

    代码如下:

      1 /// <summary>
    2 /// 转换标记
    3 /// </summary>
    4 /// <param name="sql">sql语句</param>
    5 /// <param name="columns">标记值Hashtable</param>
    6 /// <returns></returns>
    7 public DbParameter[] CastMark(ref string sql, Hashtable columns)
    8 {
    9 Regex regMark = new Regex(@":\w+");
    10 sql = regMark.Replace(sql, s =>
    11 {
    12 string mark = s.Value.Substring(1), paramName = string.Empty;
    13 if (this.dicMark.ContainsKey(mark))
    14 {
    15 paramName = this.ExistMark(mark);
    16 }
    17 else
    18 {
    19 if (columns.ContainsKey(mark))
    20 {
    21 paramName = this.NotExistMark(mark, columns[mark]);
    22 }
    23 else
    24 {
    25 throw new NullReferenceException("不存在对应的标记键值!");
    26 }
    27 }
    28 return paramName;
    29 });
    30 //返回DbParameter数组
    31 }
    32
    33 /// <summary>
    34 /// 存在标记参数
    35 /// </summary>
    36 /// <param name="mark">标记</param>
    37 /// <returns></returns>
    38 string ExistMark(string mark)
    39 {
    40 IDictionary<string, T> dicParam = this.dicMark[mark];
    41 string paramName = string.Empty;
    42 if (dicParam.Count > 1)
    43 {
    44 paramName = string.Join(",", dicParam.Keys.ToArray());
    45 }
    46 else
    47 {
    48 paramName = dicParam.First().Key;
    49 }
    50 return paramName;
    51 }
    52
    53 /// <summary>
    54 /// 不存在标记参数
    55 /// </summary>
    56 /// <param name="mark">标记</param>
    57 /// <param name="value">参数值</param>
    58 /// <returns></returns>
    59 string NotExistMark(string mark, object value)
    60 {
    61 string paramName = string.Empty;
    62 IDictionary<string, DbParameter> dicParam = new Dictionary<string, DbParameter>();
    63 if (value.GetType().IsArray)
    64 {
    65 IList values = value as IList;
    66 int length = values.Count;
    67 string[] names = new string[length];
    68 for (int i = 0; i < length; i++)
    69 {
    70 names[i] = this.GetParamName();
    71 dicParam.Add(names[i], this.CreateDbParam(names[i], values[i]));
    72 }
    73 paramName = string.Join(",", names);
    74 }
    75 else
    76 {
    77 paramName = this.GetParamName();
    78 dicParam.Add(paramName, this.CreateDbParam(paramName, value));
    79 }
    80 dicMark.Add(mark, dicParam);
    81 return paramName;
    82 }
    83
    84 /// <summary>
    85 /// 创建Db参数
    86 /// </summary>
    87 /// <param name="paramName">参数名</param>
    88 /// <param name="value">参数值</param>
    89 /// <returns></returns>
    90 DbParameter CreateDbParam(string paramName, object value)
    91 {
    92 //工厂模式,根据对应参数创建不同的DbParameter派生类
    93 }
    94
    95 /// <summary>
    96 /// 获取参数名
    97 /// </summary>
    98 /// <returns></returns>
    99 string GetParamName()
    100 {
    101 return "@Param" + index++;
    102 }


    到这里我们已经解决了大部分的问题了,但是每次都通过传入的参数来创建对应的DbParameter派生类也是一件挺麻烦的事情,我选择使用泛型去解决这个问题。

    1 public class MarkParameter<T> where T : DbParameter, new()

    这样在类内部就可以使用T来表示DbParameter的派生类了,因此一些方法就需要修改一下了。

    代码如下:

     1 /// <summary>
    2 /// 标记字典
    3 /// </summary>
    4 IDictionary<string, IDictionary<string, T>> dicMark = new Dictionary<string, IDictionary<string, T>>();
    5
    6
    7 /// <summary>
    8 /// 转换标记
    9 /// </summary>
    10 /// <param name="sql">sql语句</param>
    11 /// <param name="columns">标记值Hashtable</param>
    12 /// <returns></returns>
    13 public T[] CastMark(ref string sql, Hashtable columns)
    14 {
    15 //代码省略
    16 }
    17
    18 /// <summary>
    19 /// 创建Db参数
    20 /// </summary>
    21 /// <param name="paramName">参数名</param>
    22 /// <param name="value">参数值</param>
    23 /// <returns></returns>
    24 T CreateDbParam(string paramName, object value)
    25 {
    26 T param = new T();
    27 param.ParameterName = paramName;
    28 param.Value = value;
    29 return param;
    30 }

    到这里,我们就已经将一些主要的问题都解决掉了,完成了自己的sql参数替换了。

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法提高 交换Easy
    Java实现 蓝桥杯VIP 算法提高 多项式输出
    Java实现 蓝桥杯VIP 算法提高 多项式输出
    Java实现 蓝桥杯VIP 算法提高 多项式输出
    Java实现 蓝桥杯VIP 算法提高 多项式输出
    Java实现 蓝桥杯VIP 算法提高 多项式输出
    Java实现 蓝桥杯VIP 算法训练 矩阵乘方
    QT中给各控件增加背景图片(可缩放可旋转)的几种方法
    回调函数实现类似QT中信号机制
    std::string的Copy-on-Write:不如想象中美好(VC不使用这种方式,而使用对小字符串更友好的SSO实现)
  • 原文地址:https://www.cnblogs.com/ahl5esoft/p/2184617.html
Copyright © 2011-2022 走看看