刚进入这行业的时候,最早的时候用ADO,后来又出了各种ORM,在用了很多年后,还是觉得手写SQL最舒服,也最灵活。在各种对比后本人选择了Dapper,选择的理由是够轻量,性能好。
不管你用什么数据库框架,都会涉及到拼接SQL,可能你会说EF里不用拼接SQL,那你也得组装Expression对吧
不管你用什么工具,肯定避不开的一个就是拼接SQL,如果遇到稍复杂的逻辑,拼接SQL就很乱,可读性非常的差,如下:
var name = "jason";
var gender = 1;
var age = 18;
var sql = new StringBuilder("select * from tb where 0 = 0");
if (!string.IsNullOrWhiteSpace(name))
sql.Append(" and name=@name");
if (gender > 0)
sql.Append(" and gender=@gender");
if (age > 0)
sql.Append(" and age=@age");
或者
var name = "jason";
var gender = 1;
var age = 18;
var sql = $"select * from tb where 0=0 {(!string.IsNullOrWhiteSpace(name) ? " and name=@name" : "")} {(age > 0 ? " and age=@age" : "")} {(gender > 0 ? " and gender=@gender" : "")}";
我相信上面的写法很多人都写过,我也这么写了很多年,当你遇到比较复杂的逻辑时,这种写法可读性非常的差,别特是条件非常多的时候。后来我就想有没有什么方式,既能灵活的拼接,又有很好的可读性呢?如果要有很好的可读性,那么SQL的拼接不能放在多个条件里拼接,看到的就是一条完整的SQL语句。思考后,我写一个扩展方法,先看如何使用
var sql="select * from tb where 0=0 {and name=@name} {and gender=@gender} {and age=@age}".Splice(!string.IsNullOrWhiteSpace(name),gender>0,age>0);
用法其实有点像string.Format,每一对大括号里的字符串,是否需要,根据Splice里的对应的第几个参数是一一对应的,你看见的SQL是一个完整的SQL语句,并且支持if…else:
var status=false;
var sql="select * from tb where status={1:0}".Splice(status);
大括号内,用冒号分开,当对应参数为True时,将使用冒号前面部分,否则使用冒号的后面部分
您已经看到这里了,您觉得这样拼接是否是比上面的方式更具有可读性呢?
下面直接上实现代码,非常简单
public static string Splice(this string sql, params bool[] conditions)
{
var startIndex = 0;
foreach (var condition in conditions)
{
var start = sql.IndexOf('{', startIndex);
if (start < 0)
return sql;
var end = sql.IndexOf('}', start);
if (end < 0)
return sql;
startIndex = end;
var elseIndex = sql.IndexOf(':', start, end - start);
if (elseIndex < 0)
{
if (condition)
{
sql = sql.Remove(start, 1).Remove(end - 1, 1);
startIndex -= 2;
}
else
{
var count = end - start + 1;
sql = sql.Remove(start, count);
startIndex -= count;
}
}
else
{
if (condition)
{
var count = end - elseIndex + 1;
sql = sql.Remove(start, 1).Remove(elseIndex - 1, count);
startIndex -= count;
}
else
{
var count = elseIndex - start + 1;
sql = sql.Remove(start, count).Remove(end - count, 1);
startIndex -= count;
}
}
}
return sql;
}
也许您觉得条件多了,可读性也不好,第几个参数对应到的第几个{}呢?是的,确实有这个问题存在,但至少比前面的拼接方式的可读性好很多,我也打算自己写一个VS的VSIX扩展插件,当光标移动到Splice里的第几个参数上,前面对应的{}部分就高亮,但是不太熟悉VSIX的开发,所以迟迟没有进行。
本人对Dapper进行了封装,支持不同数据库,集成了缓存支持,性能监控,也集成了上面的拼接方法,GitHub库: https://github.com/1100100/Dapper.Extensions 如果您有更好的拼接方式,欢迎分享出来,如果您会开发VSIX扩展,可以提一个PR,感谢您的阅读。
|