在 SQLSERVER 里,我们在执行命令的时候我们是可以进行参数化传递的。这个好处主要可以防止注入。
定义接受参数的类:
public class DataParameter { public DataParameter() { } public DataParameter(string name,object value) { this.Name = name; this.Value = value; } public string Name { get; set; } public object Value { get; set; } }
我们正常写一个 Where 语句,比如 WHERE Age=23 and name like '%delaywu%' 。从这句话中我们知道一个where 表达式 是由 表字段名 + 操作符号 + 值 组成的基本操作。
所以我们创建一个方法来构建这样的SQL
private static WhereClip BuildWhereChip(string propertyName, object value, QueryOper op, string paramName=null) { if(op !=QueryOper.IsNull && op!=QueryOper.IsNotNull && (value==null || value==DBNull.Value)) { return null; } WhereClip where = new WhereClip(); StringBuilder sbSql = new StringBuilder($"{propertyName}{SqlQueryUtils.ToString(op)}"); if (value !=null && value !=DBNull.Value) { if(paramName ==null) { paramName = SqlQueryUtils.GetParmName(propertyName); } if(paramName.Length>0) { sbSql.Append($"@{paramName}"); where.Parameters.Add(new DataParameter(paramName, value)); } else { sbSql.Append($"{value}"); } } where.WhereSql = sbSql.ToString(); return where; }
public static string GetParmName(string propertyName) { //[a.name]="delaywu" string paramName = propertyName.Replace("[", "").Replace("]", ""); if(paramName.Contains(".")) { //name int lstIdx = paramName.LastIndexOf('.'); paramName = paramName.Substring(lstIdx + 1).Trim(); } if(!System.Text.RegularExpressions.Regex.IsMatch(paramName,"^[a-zA-Z1-9_]*$")) { return string.Empty; } return paramName; }
GetParmName 这个方法主要是 可能在写多表查询的时候出现 a.Name b.age 这类的情况。获得其真实的 字段名称。以及[ ] 这个信息的处理。
有了基础的构建方法。我们可以把相关操的符的 WHERE 都可以生成出来了。
public static WhereClip Eq(string propertyName, object value, string paramName = null) { return BuildWhereChip(propertyName, value, QueryOper.Eq, paramName); } public static WhereClip NotEq(string propertyName, object value, string paramName = null) { return BuildWhereChip(propertyName, value, QueryOper.NotEq, paramName); } public static WhereClip IsNull(string propertyName) { return BuildWhereChip(propertyName, null, QueryOper.IsNull, null); } public static WhereClip IsNotNull(string propertyName) { return BuildWhereChip(propertyName, null, QueryOper.IsNotNull, null); } public static WhereClip StartWith(string propertyName, string value, string paramName = null) { return Like(propertyName, value.Replace("%", "[%]").Replace("_", "[_]") + '%', paramName); } public static WhereClip EndsWith(string propertyName, string value, string paramName = null) { return Like(propertyName, '%' + value.Replace("%", "[%]").Replace("_", "[_]"), paramName); } public static WhereClip Gt(string propertyName, object value, string paramName = null) { return BuildWhereChip(propertyName, value, QueryOper.Gt, paramName); } public static WhereClip Lt(string propertyName, object value, string paramName = null) { return BuildWhereChip(propertyName, value, QueryOper.Lt, paramName); } public static WhereClip Le(string propertyName, object value, string paramName = null) { return BuildWhereChip(propertyName, value, QueryOper.Le, paramName); } public static WhereClip Ge(string propertyName, object value, string paramName = null) { return BuildWhereChip(propertyName, value, QueryOper.Ge, paramName); } public static WhereClip Like(string propertyName, string value, string paramName = null) { if (string.IsNullOrEmpty(value)) { return null; } return BuildWhereChip(propertyName, value, QueryOper.Like, paramName); } public static WhereClip Between(string propertyName, object lo, object hi, string paramName=null) { WhereClip where = new WhereClip(); StringBuilder sbSql = new StringBuilder($"{propertyName} between "); if(paramName==null) { paramName = SqlQueryUtils.GetParmName(propertyName); } if(propertyName.Length>0) { string strParamName1 = paramName + "_pmin"; string strParamName2 = paramName + "_pmax"; sbSql.Append($"@{strParamName1} and @{strParamName2} "); where.Parameters.Add(new DataParameter(strParamName1, lo)); where.Parameters.Add(new DataParameter(strParamName2, hi)); } else { sbSql.Append($"{lo} and {hi}"); } where.WhereSql = sbSql.ToString(); return where; } public static WhereClip DapperIn<T>(string propertyName,IEnumerable<T>values,string paramName=null) { if (values == null || !values.Any()) { return null; } WhereClip where = new WhereClip(); if(paramName==null) { paramName = SqlQueryUtils.GetParmName(propertyName); } if(paramName.Length>0) { where.Parameters.Add(new DataParameter(paramName, values)); where.WhereSql = $"{propertyName} in @{paramName} "; } else { if(typeof(T).FullName==typeof(string).FullName) { string strIn = string.Join<T>("','", values); where.WhereSql = $"{propertyName} in ({strIn})"; } else { string strIn = string.Join<T>(",", values); where.WhereSql = $"{propertyName} in ({strIn})"; } } return where; } public static WhereClip DapperNotIn<T>(string propertyName, IEnumerable<T> values, string paramName = null) { if (values == null || !values.Any()) { return null; } WhereClip where = new WhereClip(); if (paramName == null) { paramName = SqlQueryUtils.GetParmName(propertyName); } if (paramName.Length > 0) { where.Parameters.Add(new DataParameter(paramName, values)); where.WhereSql = $"{propertyName} not in @{paramName} "; } else { if (typeof(T).FullName == typeof(string).FullName) { string strIn = string.Join<T>("','", values); where.WhereSql = $"{propertyName} not in ('{strIn}') "; } else { string strIn = string.Join<T>(",", values); where.WhereSql = $"{propertyName} not in ({strIn}) "; } } return where; }
上面的代码。我主要说一下 Like 相关的。数据库里面我们经常使用 []来转义特殊的单词。like 中%我们是要转义的,其次_也要的。
测试一下: