• 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参数替换了。

  • 相关阅读:
    jquery easyui datebox 时间控件默认显示当前日期的实现方法
    CentOS下Web服务器环境搭建LNMP一键安装包
    EasyUI DateBox 按钮自定义添加功能
    Java程序如何生成Jar、exe及安装文件
    推荐!Sublime Text 最佳插件列表
    Sublime Text插件:HTML+CSS+JAVASCRIPT+JSON快速格式化
    java判断是excel2003还是2007以上
    Content-Type: application/vnd.ms-excel"
    小说大纲
    java判断文件真实类型
  • 原文地址:https://www.cnblogs.com/ahl5esoft/p/2184617.html
Copyright © 2020-2023  润新知