1. 程式人生 > >C#製作ORM對映學習筆記二 配置類及Sql語句生成類

C#製作ORM對映學習筆記二 配置類及Sql語句生成類

在正式開始實現ORM之前還有一點準備工作需要完成,第一是實現一個配置類,這個很簡單的就是通過靜態變數來儲存資料庫的一些連線資訊,等同於.net專案中的web.config的功能;第二需要設計實現一個sql語句的生成類來幫助生成sql語句,當前如果不實現這個類也不會影響orm的製作,之所以要做這麼一個類主要有幾個目的,1.減少sql語句中拼寫錯誤的發生。2.統一解決防sql注入的問題。

下面分別說明一下這兩個類的實現方式:

1.配置類DbConfig

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ORM
{
    public class DbConfig
    {

        /// <summary>
        /// 資料庫連線資訊
        /// </summary>
        public static string Host = "D:/C#/ORM/test.db";

        /// <summary>
        /// 資料庫型別
        /// </summary>
        public static DbType Type = DbType.Sqlite;

    }

    public enum DbType
    {
        Sqlite,
        Mysql,
        SqlServer,
        Oracle
    }
}
2.sql語句的生成類Sql
using System;
using System.Collections;
using System.Text.RegularExpressions;

namespace ORM
{
    public class Sql
    {
        /// <summary>
        /// sql語句
        /// </summary>
        private string sql;

        /// <summary>
        /// 是否有where關鍵字
        /// </summary>
        private bool hasWhere;

        /// <summary>
        /// 是否有order關鍵字
        /// </summary>
        private bool hasOrder;

        /// <summary>
        /// 防sql注入
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool InjectionDefend(string value)
        {
            //網上隨便找的,不確定是否有效
            string SqlStr = @"and|or|exec|execute|insert|select|delete|update|alter|create|drop|count|\/\*|\*\/|chr|char|asc|mid|substring|master|truncate|declare|xp_cmdshell|restore|backup|net +user|net +localgroup +administrators";
            try
            {
                if ((value != null) && (value != String.Empty))
                {
                    //string str_Regex = @"\b(" + SqlStr + @")\b";
                    Regex Regex = new Regex(SqlStr, RegexOptions.IgnoreCase);
                    if (true == Regex.IsMatch(value))
                    {
                        return false;
                    }
                }
            }
            catch
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// 建構函式
        /// </summary>
        public Sql()
        {
            sql = string.Empty;
            hasWhere = false;
            hasOrder = false;
        }

        /// <summary>
        /// 新增select
        /// </summary>
        /// <param name="column"></param>
        /// <returns></returns>
        public Sql Select(string column)
        {
            sql += ("SELECT " + column + " ");
            return this;
        }

        /// <summary>
        /// 新增from
        /// </summary>
        /// <param name="Table"></param>
        /// <returns></returns>
        public Sql From(string Table)
        {
            sql += ("FROM " + Table + " ");
            return this;
        }

        /// <summary>
        /// 新增where
        /// </summary>
        /// <param name="query"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public Sql Where(string query, params object[] values)
        {
            if (!hasWhere)
            {
                sql += "WHERE ";
                hasWhere = true;
            }
            else
            {
                sql += " AND ";
            }
            for (int i = 0; i < values.Length; i++)
            {
                Regex r = new Regex(@"@\d+");
                //bool型別需要特殊處理,不能直接用tostring轉換,因為直接轉換的結果為"True"或"False",而不是1和0
                if (values[i] is bool)
                {
                    bool value = bool.Parse(values[i].ToString());
                    query = r.Replace(query, (value ? "1" : "0"), 1);
                    continue;
                }
                else if (values[i].GetType().IsPrimitive)
                {
                    query = r.Replace(query, values[i].ToString(), 1);
                    continue;
                }
                else if (values[i].GetType().IsEnum)
                {
                    int intValue = (int)values[i];
                    query = r.Replace(query, intValue.ToString(), 1);
                    continue;
                }
                else
                {
                    if (InjectionDefend(values[i].ToString()))
                    {
                        query = r.Replace(query, "\"" + values[i].ToString() + "\"", 1);
                    }
                }
            }
            sql += query;
            return this;
        }

        /// <summary>
        /// 在sql尾部插入任意sql語句
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public Sql Append(string sql, params object[] values)
        {
            for (int i = 0; i < values.Length; i++)
            {
                Regex r = new Regex(@"@\d+");        
                if (values[i] is bool)
                {
                    bool value = bool.Parse(values[i].ToString());
                    sql = r.Replace(sql, (value ? "1" : "0"), 1);
                    continue;
                }
                else if (values[i].GetType().IsPrimitive)
                {
                    sql = r.Replace(sql, values[i].ToString(), 1);
                    continue;
                }
                else if (values[i].GetType().IsEnum)
                {
                    int intValue = (int)values[i];
                    sql = r.Replace(sql, intValue.ToString(), 1);
                    continue;
                }
                else
                {
                    if (InjectionDefend(values[i].ToString()))
                    {
                        sql = r.Replace(sql, "\"" + values[i].ToString() + "\"", 1);
                    }
                }
            }
            this.sql += (" " + sql + " ");
            return this;
        }

        /// <summary>
        /// 新增order
        /// </summary>
        /// <param name="column"></param>
        /// <returns></returns>
        public Sql OrderBy(string column)
        {
            if (!sql.EndsWith(" "))
            {
                sql += " ";
            }
            if (hasOrder)
            {
                sql += (", " + column);
            }
            else
            {
                sql += ("ORDER BY " + column);
            }
            return this;
        }


        /// <summary>
        /// 獲取當前完整的sql語句
        /// </summary>
        /// <returns></returns>
        public string GetSql()
        {
            return sql;
        }
    }
}
到這裡ORM的前期準備工作就完成了,當然Sql實現的非常簡單,像inner join、left join等sql語句的幫助生成函式都沒有做,但是實現原理時相同的,如果需要可以自己仿照實現,當然也可以直接用Append函式新增sql語句,下篇開始正式介紹ORM的核心內容。