自动SQL条件语句拼接实现

在某个项目当中,使用的使Dapper+WebApi进行构建的,在进行一些列表查询的时候需要根据不同的State来构建不同的SQL语句。之前是直接使用的switch来一个个匹配,需求增加的话,又得再加一个case。长久以往,整个查询接口臃肿不堪,离职前夕终于看不下去了,重构了一番,兹此记录。

原结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleTest
{
    public class Product
    {
        public string Name { get; set; }
        public double Price { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
        }

        public List<Product> GetByStateToList(int ConditionState)
        {
            StringBuilder _queryString = new StringBuilder();

            switch (ConditionState)
            {
                case 1:
                    _queryString.Append("查询1");
                    break;
                case 2:
                    _queryString.Append("查询2");
                    break;
                case 3:
                    _queryString.Append("查询3");
                    break;
                default:
                    _queryString.Append("查询4");
                    break;
            }
            var _queryResult = QueryDatabase(_queryString.ToString());
            return _queryResult;
        }

        public List<Product> QueryDatabase(string queryStr)
        {
            // .....查询处理
            return new List<Product>();
        }
    }
}

弊端十分明显,这里我是简化了查询语句,实际情况使每个case至少有十几行代码用于构建查询语句,随着业务变更不断加快,那么我们的GetByStateToList也会变得越来越臃肿,难以维护。

那么如何重构呢?

第一步,拆!!!

臃肿的原因就是因为在这个函数内部塞了太多的语句和分支条件,那么我们首先要把每个查询语句构建分离成一个类,将查询语句的构建放在这个独立的类内部进行操作。

第二步,统一接口

所有构建SQL语句的类都会有一个Build方法,这个方法用于构建具体的SQL语句,那么我们可以通过一个统一的接口来调用这个Build进行操作。

第三步,自动匹配

要实现自动匹配,每个类需要在其内部维护一个State常量,这个常量用于判断什么State实例化什么构造类。

下面我们就来实战演练了

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;

namespace ConsoleTest
{
    public class Product
    {
        public string Name { get; set; }
        public double Price { get; set; }
    }

    public abstract class SQLBuilder
    {
        private static List<SQLBuilder> _builders = null;
        public int State { get; protected set; }

        public static ISQLBuilder GetSQLBuilder(int state)
        {
            if (_builders == null)
            {
                _builders = new List<SQLBuilder>();
                var _types = Assembly.GetExecutingAssembly().GetTypes();
                foreach (var _type in _types)
                {
                    if (_type.GetInterface(typeof(ISQLBuilder).FullName) != null)
                    {
                        _builders.Add(Activator.CreateInstance(_type) as SQLBuilder);
                    }
                }
            }

            var _builder = _builders.Where(x => x.State == state).FirstOrDefault();
            return _builder as ISQLBuilder;
        }
    }

    public interface ISQLBuilder
    {
        string Build();
    }

    public class SQLBuilderNo1 : SQLBuilder, ISQLBuilder
    {
        public SQLBuilderNo1() => State = 1;

        public string Build() => "查询1";
    }

    public class SQLBuilderNo2 : SQLBuilder, ISQLBuilder
    {
        public SQLBuilderNo2() => State = 2;

        public string Build() => "查询2";
    }

    public class SQLBuilderNo3 : SQLBuilder, ISQLBuilder
    {
        public SQLBuilderNo3() => State = 3;

        public string Build() => "查询3";
    }

    class Program
    {
        static void Main(string[] args)
        {
            ISQLBuilder _builder = SQLBuilder.GetSQLBuilder(2);
            Console.WriteLine(_builder.Build());
            _builder = SQLBuilder.GetSQLBuilder(3);
            Console.WriteLine(_builder.Build());
            Console.ReadKey();
        }

        public List<Product> GetByStateToList(int ConditionState)
        {
            string _queryStr = string.Empty;

            var _queryResult = QueryDatabase(_queryStr);
            return _queryResult;
        }

        public List<Product> QueryDatabase(string queryStr)
        {
            // .....查询处理
            return new List<Product>();
        }
    }
}

结果: image_1bqi9ff86bne12g3b1j5f1fq49.png-19kB

Licensed under CC BY-NC-SA 4.0
Built with Hugo
主题 StackJimmy 设计