• 自己动手写ORM(02):Sql生成器实现


    上一节中鄙人通过解析表达式树生成Sql碎片,其中我也把解析表达式类代码贴了出来,文章发布之后我对ExpressionAnalyzer类做了些改动,下面我还会将代码贴出来,废话不多说,直接进入今天的主题。

    实体类设计:

      首先,我觉得要想直接通过实体类生成Sql语句,那么你可能要知道这个实体类对应数据库表中的主键和外键是什么,在此我加入了两个特性来标识主键和外键关系。如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    /// <summary>
        /// 外键表特性(导航属性)
        /// </summary>
        public class GuidanceAttribute : System.Attribute
        {
            /// <summary>
            /// 依赖字段
            /// </summary>
            public string DepandField { getset; }
        }
     
     public class MessageAttribute : System.Attribute
        {
            /// <summary>
            /// 链接字符串名
            /// </summary>
            public string ConStr { getset; }
        }
     public class PrimaryKeyAttribute : System.Attribute
        {
     
        }

      实体类如下:

    复制代码
     1 using LC.Model;
     2 using LC.Model.Attribute;
     3 using System;
     4 using System.Collections.Generic;
     5 using System.Linq;
     6 using System.Text;
     7 using System.Threading.Tasks;
     8 using LC.Model.Common;
     9 using LC.Test;
    10 using LC.Test.Model;
    11 
    12 namespace LC.Model
    13 {
    14     [Message(ConStr = "sql")]
    15     public class SYS_User
    16     {
    17         [PrimaryKey]
    18         public string Id { get; set; }
    19         public string UserName { get; set; }
    20 
    21         public Guid? RoleId { get; set; }
    22         public Guid? CityId { get; set; }
    23         [Guidance(DepandField = "RoleId")]
    24         public SYS_Role Role { get; set; }
    25 
    26         [Guidance(DepandField = "CityId")]
    27         public City City { get; set; }
    28 
    29         public int Gender { get; set; }
    30 
    31         public bool Deleted { get; set; }
    32 
    33         public DateTime CreateTime { get; set; }
    34     }
    35 }
    复制代码

      那么在生成sql的过程中,我需要知道实体所对应表的主键和外键关系,此关系我保存在类TableInfo中:

    复制代码
    1  public class TableInfo
    2     {
    3         public string ConStr { get; set; }
    4         public string RName { get; set; }
    5         public string TableName { get; set; }
    6         public string PrimaryKey { get; set; }
    7         public Dictionary<string, TableInfo> ForeignRefs { get; set; }
    8     }
    复制代码

      具体怎么将实体类转换成TableInfo,在此我暂时使用反射,不过多解释,因为暂时还不知道有什么方法不用反射获取特性。

      有了TableInfo,我们就可以轻松的生成Sql了。

    查询命令生成器设计:

      下面上图,这是我用画图工具话的,不要问我为什么,因为电脑没有建模工具。。。

      

      直接上代码:

      

    复制代码
     1     public interface ICreator
     2     {
     3         SqlDebris Debris { get; set; }
     4     }
     5 
     6     public class BaseCreator : ICreator
     7     {
     8         public SqlDebris Debris { get; set; }
     9         public BaseCreator()
    10         {
    11             Debris = new SqlDebris();
    12         }
    13     }
    14     public interface IQuery : ICreator
    15     {
    16         void CreateFrom(AnalysisTable data, TableInfo tableInfo);
    17         void CreateSelect(AnalysisData data);
    18         void CreateWhere(AnalysisData data);
    19         void AppendOrder(AnalysisData data, OrderTypeEnum orderType);
    20         void AppendSkip(int count);
    21         void AppendTake(int count);
    22         void GetCount();
    23     }
    复制代码

      下面是QueryCreator的实现:

    复制代码
      1  public class QueryCreator : BaseCreator, IQuery
      2     {
      3         public virtual void CreateSelect(AnalysisData data)
      4         {
      5             var primaryTable = data.Table;
      6             StringBuilder sb = new StringBuilder();
      7             //默认查询全部列
      8             if (data.StackList.Count <= 0)
      9             {
     10                 sb.AppendFormat("[{0}].*", primaryTable.RName);
     11             }
     12             else
     13             {
     14                 //查询部分列
     15                 for (int i = 0; i < data.StackList.Count; i += 3)
     16                 {
     17                     sb.AppendFormat("{0} {1} {2},", data.StackList[i], data.StackList[i + 1], data.StackList[i + 2]);
     18                 }
     19                 sb.Remove(sb.Length - 1, 1);
     20             }
     21             Debris.Select = sb.ToString();
     22         }
     23         public virtual void CreateFrom(AnalysisTable anlyTable, TableInfo tableInfo)
     24         {
     25             if (null == anlyTable)
     26             {
     27                 throw new BusinessException(BusinessRes.TableCanNotBeEmpty);
     28             }
     29             //默认排序信息
     30             if (string.IsNullOrEmpty(Debris.Order))
     31             {
     32                 Debris.Order = string.Format("[{0}].{1} {2}", anlyTable.RName, tableInfo.PrimaryKey, System.Enum.GetName(typeof(OrderTypeEnum), OrderTypeEnum.ASC));
     33             }
     34             StringBuilder sb = new StringBuilder();
     35             sb.AppendFormat("[{0}] AS [{1}]", anlyTable.Name, anlyTable.RName);
     36             AppendLeftJoinTables(anlyTable, tableInfo, sb);
     37             Debris.From = sb.ToString();
     38         }
     39         public virtual void CreateWhere(AnalysisData data)
     40         {
     41             if (data == null || data.StackList.Count() <= 0)
     42             {
     43                 return;
     44             }
     45             Debris.Where = string.Join(" ", data.StackList);
     46         }
     47         public virtual void AppendSkip(int count)
     48         {
     49             Debris.Skip = count;
     50         }
     51         public virtual void AppendTake(int count)
     52         {
     53             Debris.Take = count;
     54         }
     55         public virtual void AppendOrder(AnalysisData data, OrderTypeEnum orderType)
     56         {
     57             if (data.StackList.Count <= 0)
     58             {
     59                 return;
     60             }
     61             var field = data.StackList.First();
     62             StringBuilder sb = new StringBuilder(Debris.Order);
     63             if (string.IsNullOrEmpty(Debris.Order))
     64             {
     65                 sb.AppendFormat("{0} {1}", field, System.Enum.GetName(typeof(OrderTypeEnum), orderType));
     66                 Debris.Order = sb.ToString();
     67                 return;
     68             }
     69             sb.AppendFormat(",{0} {1}", field, System.Enum.GetName(typeof(OrderTypeEnum), orderType));
     70             Debris.Order = sb.ToString();
     71         }
     72         public void GetCount()
     73         {
     74             Debris.Select = "COUNT(1)";
     75         }
     76 
     77         private KeyValuePair<string, TableInfo> GetForeignReference(TableInfo tInfo, string rName)
     78         {
     79             var keyValue = tInfo.ForeignRefs.Where(u => u.Value.RName == rName).FirstOrDefault();
     80             if (string.IsNullOrEmpty(keyValue.Key))
     81             {
     82                 foreach (var item in tInfo.ForeignRefs)
     83                 {
     84                     var foreignTable = GetForeignReference(item.Value, rName);
     85                     if (!string.IsNullOrEmpty(keyValue.Key))
     86                     {
     87                         return foreignTable;
     88                     }
     89                 }
     90 
     91             }
     92 
     93             return keyValue;
     94         }
     95         private void AppendLeftJoinTables(AnalysisTable anlyTable, TableInfo tableInfo, StringBuilder sb)
     96         {
     97             ///添加关系表信息
     98             foreach (var item in anlyTable.leftJoins)
     99             {
    100                 var _foreignRef = GetForeignReference(tableInfo, item.RName);
    101                 if (string.IsNullOrEmpty(_foreignRef.Key))
    102                 {
    103                     throw new BusinessException(BusinessRes.WhitoutThisForeignReference);
    104                 }
    105                 sb.AppendFormat(" LEFT JOIN [{0}] AS [{1}] ON [{1}].{2}=[{3}].{4} ", item.Name, item.RName, _foreignRef.Value.PrimaryKey, anlyTable.RName, _foreignRef.Key);
    106                 AppendLeftJoinTables(item, _foreignRef.Value, sb);
    107             }
    108         }
    109     }
    复制代码

      到此为止,生成的Sql依然是不完整的Sql碎片,我们需要将碎片合并成Sql语句,我写了一个工具类如下:

      保存碎片类:

    复制代码
     1 public class SqlDebris
     2     {
     3         public string Where { get; set; }
     4         #region 查询
     5         public string From { get; set; }
     6         public string Select { get; set; }
     7         public string Order { get; set; }
     8         public int Skip { get; set; }
     9         public int? Take { get; set; }
    10         #endregion
    11         #region 修改
    12         public string Set { get; set; }
    13         public string Update { get; set; }
    14         #endregion
    15         #region 新增
    16 
    17         public string InsertTable { get; set; }
    18         public string Columns { get; set; }
    19         public string Values { get; set; }
    20 
    21         #endregion
    22     }
    复制代码

      通过下面工具类生成完整Sql语句:

    复制代码
     1 public class CommandTextHelper
     2     {
     3         public static string GetSelectCommandText(ICreator creator)
     4         {
     5             var debris = creator.Debris;
     6             StringBuilder sb = new StringBuilder();
     7             if (debris.Take == null)
     8             {
     9                 sb.Append(" SELECT * FROM (");
    10             }
    11             else
    12             {
    13                 //分页
    14                 sb.AppendFormat(" SELECT TOP {0} * FROM (", debris.Take);
    15             }
    16             sb.AppendFormat("SELECT {0},ROW_NUMBER() OVER(ORDER BY  {2} ) as ROWNUMBER  FROM {1}", debris.Select, debris.From, debris.Order);
    17             //条件
    18             if (!string.IsNullOrEmpty(debris.Where))
    19             {
    20                 sb.AppendFormat(" WHERE {0} ", debris.Where);
    21             }
    22             sb.Append(") as NEW_TABLE ");
    23             sb.AppendFormat(" WHERE ROWNUMBER>{0}", debris.Skip);
    24             return sb.ToString();
    25         }
    26 
    27         public static string GetCountCommandText(ICreator creator)
    28         {
    29             var debris = creator.Debris;
    30             StringBuilder sb = new StringBuilder();
    31 
    32             sb.AppendFormat("SELECT {0} FROM {1}", debris.Select, debris.From);
    33             //条件
    34             if (!string.IsNullOrEmpty(debris.Where))
    35             {
    36                 sb.AppendFormat(" WHERE {0} ", debris.Where);
    37             }
    38             return sb.ToString();
    39         }
    40 
    41         public static string GetUpdateCommandText(ICreator creator)
    42         {
    43             var debris = creator.Debris;
    44             StringBuilder sb = new StringBuilder();
    45             sb.AppendFormat("UPDATE {0} ", debris.Update);
    46             sb.AppendFormat("SET {0} ", debris.Set);
    47             sb.AppendFormat("WHERE {0}", debris.Where);
    48             return sb.ToString();
    49         }
    50         public static string GetInsertCommandText(ICreator creator)
    51         {
    52             var debris = creator.Debris;
    53             StringBuilder sb = new StringBuilder();
    54             sb.AppendFormat("INSERT INTO {0}", debris.InsertTable);
    55             sb.AppendFormat("({0}) ", debris.Columns);
    56             sb.AppendFormat("VALUES({0})", debris.Values);
    57             return sb.ToString();
    58         }
    59         public static string GetDeleteCommandText(ICreator creator)
    60         {
    61             var debris = creator.Debris;
    62             StringBuilder sb = new StringBuilder();
    63             sb.AppendFormat("DELETE FROM {0}", debris.From);
    64             sb.AppendFormat(" WHERE {0}", debris.Where);
    65             return sb.ToString();
    66         }
    67     }
    复制代码

      下面是CommandFactory<TEntity>:

    复制代码
    1  public class CommandFactory<TEntity> 
    2     {
    3         protected TableInfo _tableInfo;
    4         public CommandFactory()
    5         {
    6             _tableInfo = new Mapper().MapToTable(typeof(TEntity));
    7         }
    8     }
    复制代码

      

    下面是QueryCommand<TEntity>实现:

    复制代码
     1  public class QueryCommand<TEntity> : CommandFactory<TEntity>
     2     {
     3         //sql碎片生成器
     4         private IQuery _creator;
     5         //查询参数
     6         private Dictionary<string, object> _params;
     7 
     8         private AnalysisTable _table;
     9 
    10         public QueryCommand()
    11         {
    12             _creator = new QueryCreator();
    13         }
    14         public QueryCommand<TEntity> Where(Expression<Func<TEntity, bool>> exp)
    15         {
    16             var retData = new ExpressionAnalyzer(exp).GetAnalysisResult();
    17             _creator.CreateWhere(retData);
    18             _params = retData.ParamList;
    19             _table = retData.Table;
    20             return this;
    21         }
    22         public QueryCommand<TEntity> OrderBy(Expression<Func<TEntity, object>> exp)
    23         {
    24             _creator.AppendOrder(new ExpressionAnalyzer(exp).GetAnalysisResult(), OrderTypeEnum.ASC);
    25             return this;
    26         }
    27         public QueryCommand<TEntity> OrderByDescding(Expression<Func<TEntity, object>> exp)
    28         {
    29             _creator.AppendOrder(new ExpressionAnalyzer(exp).GetAnalysisResult(), OrderTypeEnum.DESC);
    30             return this;
    31         }
    32         public QueryCommand<TEntity> ThenBy(Expression<Func<TEntity, object>> exp)
    33         {
    34             return OrderBy(exp);
    35         }
    36         public QueryCommand<TEntity> ThenByDescding(Expression<Func<TEntity, object>> exp)
    37         {
    38             return OrderByDescding(exp);
    39         }
    40         public QueryCommand<TEntity> Skip(int count)
    41         {
    42             _creator.AppendSkip(count);
    43             return this;
    44         }
    45         public QueryCommand<TEntity> Take(int count)
    46         {
    47             _creator.AppendTake(count);
    48             return this;
    49         }
    50         public Command<TResult> GetSelectCommand<TResult>(Expression<Func<TEntity, TResult>> exp)
    51         {
    52             var _result = new ExpressionAnalyzer(exp, _table).GetAnalysisResult();
    53             _creator.CreateSelect(_result);
    54             _creator.CreateFrom(_result.Table, _tableInfo);
    55             return new Command<TResult>()
    56             {
    57                 ConStr = _tableInfo.ConStr,
    58                 CommandText = CommandTextHelper.GetSelectCommandText(_creator),
    59                 Params = _params
    60             };
    61         }
    62         public Command<int> GetCountCommand(Expression<Func<TEntity, bool>> exp)
    63         {
    64             var retData = new ExpressionAnalyzer(exp).GetAnalysisResult();
    65             _creator.CreateWhere(retData);
    66             _creator.GetCount();
    67             _creator.CreateFrom(retData.Table, _tableInfo);
    68             return new Command<int>()
    69             {
    70                 CommandText = CommandTextHelper.GetCountCommandText(_creator),
    71                 ConStr = _tableInfo.ConStr,
    72                 Params = retData.ParamList
    73             };
    74         }
    75     }
    复制代码

      下面是测试结果仅供参考:

    复制代码
     1         [TestMethod]
     2         public void TestQueryCommand()
     3         {
     4             var param = new SYS_User()
     5             {
     6                 UserName = "lichun",
     7                 RoleId = Guid.NewGuid()
     8             };
     9             QueryCommand<SYS_User> f = new QueryCommand<SYS_User>();
    10             var command = f.Where(u => u.City.Name == "cengdu" && u.Role.Config.Name.Contains(param.UserName)).GetSelectCommand(u => new
    11             {
    12                 u.Id,
    13                 u.Role.Name
    14             });
    15             ShowCommand(command);
    16         }    
    17 
    18 
    19         public void ShowCommand<TResult>(Command<TResult> command)
    20         {
    21        Console.WriteLine("链接字符串:");
    22             Console.WriteLine(command.ConStr);
    23             Console.WriteLine("----------------------------------");
             Console.WriteLine("Sql命令:"); 24 Console.WriteLine(command.CommandText); 25 26 Console.WriteLine("----------------------------------"); 27 if (command.Params != null) 28 {
               Console.WriteLine("参数:"); 29 foreach (var item in command.Params) 30 { 31 32 Console.WriteLine("{0} → {1}", item.Key, item.Value); 33 } 34 } 35 36 }
    复制代码

    测试结果如下:

      

      修改的ExpressionAnalyzer如下:

    复制代码
      1  public class ExpressionAnalyzer
      2     {
      3         /// <summary>
      4         /// 表达式所有参数集合
      5         /// </summary>
      6         private Dictionary<string, object> _params;
      7         /// <summary>
      8         /// 命名参数别名
      9         /// </summary>
     10         private const string _argName = "TAB";
     11         /// <summary>
     12         /// 解析结果
     13         /// </summary>
     14         private AnalysisData _resultData;
     15 
     16         public ExpressionAnalyzer()
     17         {
     18             _resultData = new AnalysisData();
     19             _params = new Dictionary<string, object>();
     20         }
     21         public ExpressionAnalyzer(LambdaExpression exp, AnalysisTable table = null)
     22             : this()
     23         {
     24             if (table != null)
     25             {
     26                 _resultData.Table = table;
     27             }
     28 
     29             if (exp != null)
     30             {
     31                 AppendParams(GetChildValue(exp.Body), _params);
     32                 foreach (var item in exp.Parameters)
     33                 {
     34                     AnalysisTables(item);
     35                 }
     36                 AnalysisExpression(exp.Body, true);
     37             }
     38         }
     39 
     40 
     41 
     42         public AnalysisData GetAnalysisResult()
     43         {
     44             return _resultData;
     45         }
     46 
     47 
     48         /// <summary>
     49         /// 解析表达式
     50         /// </summary>
     51         /// <param name="exp"></param>
     52         /// <param name="isLeftChild"></param>
     53         private void AnalysisExpression(Expression exp, bool isLeftChild = true)
     54         {
     55             switch (exp.NodeType)
     56             {
     57                 case ExpressionType.AndAlso:
     58                     _resultData.StackList.Add("(");
     59                     AnalysisExpression(GetChildExpression(exp));
     60                     _resultData.StackList.Add(")");
     61                     _resultData.StackList.Add("AND");
     62                     _resultData.StackList.Add("(");
     63                     AnalysisExpression(GetChildExpression(exp, false), false);
     64                     _resultData.StackList.Add(")");
     65                     break;
     66                 case ExpressionType.OrElse:
     67                     _resultData.StackList.Add("(");
     68                     AnalysisExpression(GetChildExpression(exp));
     69                     _resultData.StackList.Add(")");
     70                     _resultData.StackList.Add("OR");
     71                     _resultData.StackList.Add("(");
     72                     AnalysisExpression(GetChildExpression(exp, false), false);
     73                     _resultData.StackList.Add(")");
     74                     break;
     75                 case ExpressionType.Equal:
     76                     AnalysisExpression(GetChildExpression(exp));
     77                     _resultData.StackList.Add("=");
     78                     AnalysisExpression(GetChildExpression(exp, false), false);
     79                     break;
     80                 case ExpressionType.NotEqual:
     81                     AnalysisExpression(GetChildExpression(exp));
     82                     _resultData.StackList.Add("!=");
     83                     AnalysisExpression(GetChildExpression(exp, false), false);
     84                     break;
     85                 case ExpressionType.GreaterThanOrEqual:
     86                     AnalysisExpression(GetChildExpression(exp));
     87                     _resultData.StackList.Add(">=");
     88                     AnalysisExpression(GetChildExpression(exp, false), false);
     89                     break;
     90                 case ExpressionType.GreaterThan:
     91                     AnalysisExpression(GetChildExpression(exp));
     92                     _resultData.StackList.Add(">");
     93                     AnalysisExpression(GetChildExpression(exp, false), false);
     94                     break;
     95                 case ExpressionType.LessThan:
     96                     AnalysisExpression(GetChildExpression(exp));
     97                     _resultData.StackList.Add("<");
     98                     AnalysisExpression(GetChildExpression(exp, false), false);
     99                     break;
    100                 case ExpressionType.LessThanOrEqual:
    101                     AnalysisExpression(GetChildExpression(exp));
    102                     _resultData.StackList.Add("<=");
    103                     AnalysisExpression(GetChildExpression(exp, false), false);
    104                     break;
    105                 case ExpressionType.Call:
    106                     var imExp = exp as MethodCallExpression;
    107                     AnalysisExpression(imExp.Object, true);
    108                     _resultData.StackList.Add("LIKE");
    109                     if (imExp.Arguments.Count > 0)
    110                     {
    111                         var arg0 = imExp.Arguments[0] as MemberExpression;
    112                         _resultData.StackList.Add("'%'+");
    113                         AnalysisExpression(imExp.Arguments[0], false);
    114                         _resultData.StackList.Add("+'%'");
    115                     }
    116                     break;
    117                 case ExpressionType.MemberAccess:
    118                     if (isLeftChild)
    119                     {
    120                         AnalysisTables(exp);
    121                         var mberExp = exp as MemberExpression;
    122                         var parentName = GetExpressionName(mberExp.Expression);
    123                         if (!string.IsNullOrEmpty(parentName))
    124                         {
    125                             _resultData.StackList.Add(string.Format("[{0}].{1}", parentName, GetExpressionName(exp)));
    126                             break;
    127                         }
    128                         _resultData.StackList.Add(GetExpressionName(exp));
    129                     }
    130                     else
    131                     {
    132                         var paramName = GetParamName(exp);
    133                         _resultData.ParamList.Add(paramName, _params[paramName]);
    134                         _resultData.StackList.Add(paramName);
    135                     }
    136                     break;
    137                 case ExpressionType.Constant:
    138                     var constent = exp as ConstantExpression;
    139                     if (constent.Value == null)
    140                     {
    141                         var op = _resultData.StackList.ElementAt(_resultData.StackList.Count - 1);
    142                         _resultData.StackList.RemoveAt(_resultData.StackList.Count - 1);
    143                         if (string.Equals(op, "="))
    144                         {
    145                             _resultData.StackList.Add("IS NULL");
    146                         }
    147                         else
    148                         {
    149                             _resultData.StackList.Add("IS NOT NULL");
    150                         }
    151                         break;
    152                     }
    153                     if (constent.Value.GetType() == typeof(String))
    154                     {
    155                         _resultData.StackList.Add(string.Format("'{0}'", constent.Value));
    156                         break;
    157                     }
    158                     if (constent.Value.GetType() == typeof(bool))
    159                     {
    160                         if (_resultData.StackList.Count > 0)
    161                         {
    162                             var value = Convert.ToBoolean(constent.Value);
    163                             _resultData.StackList.Add(string.Format("{0}", value ? "1" : "0"));
    164                         }
    165 
    166                         break;
    167                     }
    168                     _resultData.StackList.Add(string.Format("{0}", constent.Value));
    169                     break;
    170                 case ExpressionType.Convert:
    171                     var uExp = exp as UnaryExpression;
    172                     AnalysisExpression(uExp.Operand, isLeftChild);
    173                     break;
    174                 case ExpressionType.New:
    175                     var newExp = exp as NewExpression;
    176                     //解析查询字段
    177                     for (int i = 0; i < newExp.Arguments.Count; i++)
    178                     {
    179                         AnalysisExpression(newExp.Arguments[i]);
    180                         _resultData.StackList.Add("AS");
    181                         _resultData.StackList.Add(string.Format("'{0}'", newExp.Members[i].Name));
    182                     }
    183                     break;
    184                 case ExpressionType.Parameter:
    185                     throw new BusinessException(BusinessRes.SelectObjectMastBeAnNewObject);
    186                 //AnalysisExpression(Expression.New(exp.Type));
    187                 //break;
    188                 default:
    189                     break;
    190             }
    191 
    192         }
    193         /// <summary>
    194         /// 获取孩子节点
    195         /// </summary>
    196         /// <param name="exp"></param>
    197         /// <param name="getLeft"></param>
    198         /// <returns></returns>
    199         private Expression GetChildExpression(Expression exp, bool getLeft = true)
    200         {
    201             var className = exp.GetType().Name;
    202             switch (className)
    203             {
    204                 case "BinaryExpression":
    205                 case "LogicalBinaryExpression":
    206                     var bExp = exp as BinaryExpression;
    207                     return getLeft ? bExp.Left : bExp.Right;
    208                 case "PropertyExpression":
    209                 case "FieldExpression":
    210                     var mberExp = exp as MemberExpression;
    211                     return mberExp;
    212                 case "MethodBinaryExpression":
    213                     var mbExp = exp as BinaryExpression;
    214                     return getLeft ? mbExp.Left : mbExp.Right;
    215                 case "UnaryExpression":
    216                     var unaryExp = exp as UnaryExpression;
    217                     return unaryExp;
    218                 case "ConstantExpression":
    219                     var cExp = exp as ConstantExpression;
    220                     return cExp;
    221                 case "InstanceMethodCallExpressionN":
    222                     var imExp = exp as MethodCallExpression;
    223                     return imExp;
    224                 default:
    225                     return null;
    226             }
    227         }
    228         /// <summary>
    229         /// 获取变量名
    230         /// </summary>
    231         /// <param name="exp"></param>
    232         /// <param name="isLeftChild"></param>
    233         /// <returns></returns>
    234         private string GetExpressionName(Expression exp)
    235         {
    236             var className = exp.GetType().Name;
    237             switch (className)
    238             {
    239                 case "PropertyExpression":
    240                 case "FieldExpression":
    241                     var mberExp = exp as MemberExpression;
    242                     return string.Format("{0}", mberExp.Member.Name);
    243                 case "TypedParameterExpression":
    244                     return _argName;
    245                 default:
    246                     return string.Empty;
    247             }
    248         }
    249         /// <summary>
    250         /// 获取参数名
    251         /// </summary>
    252         /// <param name="exp"></param>
    253         /// <param name="isLeftChild"></param>
    254         /// <returns></returns>
    255         private string GetParamName(Expression exp)
    256         {
    257             var className = exp.GetType().Name;
    258             switch (className)
    259             {
    260                 case "PropertyExpression":
    261                 case "FieldExpression":
    262                     var mberExp = exp as MemberExpression;
    263                     return string.Format("@{0}", mberExp.Member.Name);
    264                 case "TypedParameterExpression":
    265                     var texp = exp as ParameterExpression;
    266                     return string.Format("@{0}", texp.Name);
    267                 default:
    268                     return string.Empty;
    269             }
    270         }
    271         /// <summary>
    272         /// 解析表信息
    273         /// </summary>
    274         /// <param name="exp"></param>
    275         /// <param name="refTable">引用表</param>
    276         private void AnalysisTables(Expression exp, AnalysisTable refTable = null)
    277         {
    278             var className = exp.GetType().Name;
    279             switch (className)
    280             {
    281                 case "PropertyExpression":
    282                 case "FieldExpression":
    283                     var mberExp = exp as MemberExpression;
    284                     if (IsDefaultType(mberExp.Type))
    285                     {
    286                         AnalysisTables(mberExp.Expression);
    287                         break;
    288                     }
    289                     var _tampTab = GetTableByRName(_resultData.Table, mberExp.Member.Name);
    290                     if (_tampTab == null)
    291                     {
    292                         _tampTab = new AnalysisTable()
    293                          {
    294                              RName = mberExp.Member.Name,
    295                              Name = mberExp.Type.Name,
    296                              TableType = mberExp.Type
    297 
    298                          };
    299                         AnalysisTables(mberExp.Expression, _tampTab);
    300                     }
    301                     if (refTable != null)
    302                     {
    303                         _tampTab.leftJoins.Add(refTable);
    304                     }
    305                     break;
    306                 case "TypedParameterExpression":
    307                     //命名参数表达式
    308                     var texp = exp as ParameterExpression;
    309                     if (!IsDefaultType(texp.Type))
    310                     {
    311                         if (null == _resultData.Table)
    312                         {
    313                             _resultData.Table = new AnalysisTable()
    314                              {
    315                                  RName = _argName,
    316                                  Name = texp.Type.Name,
    317                                  TableType = texp.Type
    318                              };
    319                         }
    320                         if (refTable != null)
    321                         {
    322                             _resultData.Table.leftJoins.Add(refTable);
    323                         }
    324                     }
    325                     break;
    326                 default:
    327                     break;
    328             }
    329         }
    330         /// <summary>
    331         /// 遍历树,深度优先
    332         /// </summary>
    333         /// <param name="table"></param>
    334         /// <param name="rName"></param>
    335         /// <returns></returns>
    336         private AnalysisTable GetTableByRName(AnalysisTable table, string rName)
    337         {
    338             var _tempTable = table;
    339             if (_tempTable.RName == rName)
    340             {
    341                 return _tempTable;
    342             }
    343             foreach (var item in _tempTable.leftJoins)
    344             {
    345                 _tempTable = GetTableByRName(item, rName);
    346                 if (_tempTable != null)
    347                 {
    348                     return _tempTable;
    349                 }
    350             }
    351             return null;
    352         }
    353         /// <summary>
    354         /// 解析获取表达式的值
    355         /// </summary>
    356         /// <param name="exp"></param>
    357         /// <param name="leftChild"></param>
    358         /// <returns></returns>
    359         private object GetChildValue(Expression exp)
    360         {
    361             var className = exp.GetType().Name;
    362             switch (className)
    363             {
    364                 case "BinaryExpression":
    365                 case "LogicalBinaryExpression":
    366                     var lExp = exp as BinaryExpression;
    367                     var ret = GetChildValue(lExp.Left);
    368                     if (IsNullDefaultType(ret))
    369                     {
    370                         ret = GetChildValue(lExp.Right);
    371                     }
    372                     return ret;
    373                 case "MethodBinaryExpression":
    374                     var mbExp = exp as BinaryExpression;
    375                     var ret1 = GetChildValue(mbExp.Left);
    376                     if (IsNullDefaultType(ret1))
    377                     {
    378                         ret1 = GetChildValue(mbExp.Right);
    379                     }
    380                     return ret1;
    381 
    382                 case "PropertyExpression":
    383                 case "FieldExpression":
    384                     var mberExp = exp as MemberExpression;
    385                     return GetChildValue(mberExp.Expression);
    386                 case "ConstantExpression":
    387                     var cExp = exp as ConstantExpression;
    388                     return cExp.Value;
    389                 case "UnaryExpression":
    390                     var unaryExp = exp as UnaryExpression;
    391                     return GetChildValue(unaryExp.Operand);
    392                 case "InstanceMethodCallExpressionN":
    393                     var imExp = exp as MethodCallExpression;
    394                     if (imExp.Arguments.Count > 0)
    395                     {
    396                         return GetChildValue(imExp.Arguments[0]);
    397                     }
    398                     return null;
    399                 default:
    400                     return null;
    401             }
    402 
    403         }
    404         /// <summary>
    405         /// 初始化所有参数
    406         /// </summary>
    407         /// <param name="paramObj"></param>
    408         private void AppendParams(object paramObj, Dictionary<string, object> _params)
    409         {
    410             if (IsNullDefaultType(paramObj))
    411             {
    412                 return;
    413             }
    414             if (_params == null)
    415             {
    416                 _params = new Dictionary<string, object>();
    417             }
    418             foreach (var item in paramObj.GetType().GetProperties())
    419             {
    420                 if (IsDefaultType(item.PropertyType))
    421                 {
    422                     var value = item.GetValue(paramObj, null);
    423                     if (value != null)
    424                     {
    425                         _params.Add(string.Format("@{0}", item.Name), value);
    426                     }
    427                     continue;
    428                 }
    429 
    430                 AppendParams(item.GetValue(paramObj), _params);
    431             }
    432 
    433             foreach (var item in paramObj.GetType().GetFields())
    434             {
    435                 if (IsDefaultType(item.FieldType))
    436                 {
    437                     var value = item.GetValue(paramObj);
    438                     if (value != null)
    439                     {
    440                         _params.Add(string.Format("@{0}", item.Name), value);
    441                     }
    442                     continue;
    443                 }
    444                 AppendParams(item.GetValue(paramObj), _params);
    445             }
    446         }
    447         public Dictionary<string, object> GetParams(object paramObj)
    448         {
    449             Dictionary<string, object> dicParams = new Dictionary<string, object>();
    450             AppendParams(paramObj, dicParams);
    451             return dicParams;
    452         }
    453         /// <summary>
    454         /// 判断是否是系统默认基本类型
    455         /// </summary>
    456         /// <param name="type"></param>
    457         /// <returns></returns>
    458         private bool IsNullDefaultType(object obj)
    459         {
    460             if (obj == null)
    461             {
    462                 return true;
    463             }
    464             return IsDefaultType(obj.GetType());
    465         }
    466         private bool IsDefaultType(Type type)
    467         {
    468             string defaultType = @"String|Boolean|Double|Int32|Int64|Int16|Single|DateTime|Decimal|Char|Object|Guid";
    469 
    470             Regex e = new Regex(defaultType, RegexOptions.IgnoreCase);
    471             if (type.Name.ToLower().Contains("nullable"))
    472             {
    473                 if (type.GenericTypeArguments.Count() > 0)
    474                 {
    475                     return e.IsMatch(type.GenericTypeArguments[0].Name);
    476                 }
    477             }
    478             return e.IsMatch(type.Name);
    479         }
    480     }
    复制代码

      共同学习共同进步,表达有些乱,希望各位大神多多包涵。

  • 相关阅读:
    个人浏览器安装的插件
    angularjs 1 Failed to read the 'selectionStart' property from 'HTMLInputElement':
    git 配置用户名和邮箱
    修改Atom 隐藏.gitignore忽略的文件/文件夹的配置
    Ubuntu 安装php_intl 扩展
    yii2 ./yii command : No such file or directory
    vagrant yii2 Exception 'yiidbException' with message 'SQLSTATE[HY000] [2002]
    [转载]Ubuntu 14.04设置固定ip
    [转载]删除所有的.svn文件夹
    Centos7.2正常启动关闭CDH5.16.1
  • 原文地址:https://www.cnblogs.com/sjqq/p/8428611.html
Copyright © 2020-2023  润新知