你的位置:首页 > ASP.net教程

[ASP.net教程]自己动手写ORM(02):Sql生成器实现


回顾:

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

实体类设计:

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

/// <summary>  /// 外键表特性(导航属性)  /// </summary>  public class GuidanceAttribute : System.Attribute  {    /// <summary>    /// 依赖字段    /// </summary>    public string DepandField { get; set; }  } public class MessageAttribute : System.Attribute  {    /// <summary>    /// 链接字符串名    /// </summary>    public string ConStr { get; set; }  } 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.Model13 {14   [Message(ConStr = "sql")]15   public class SYS_User16   {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 }

View Code

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

1 public class TableInfo2   {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   }

View Code

  具体怎么将实体类转换成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 : ICreator15   {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   }

View Code

  下面是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   }

View Code

  到此为止,生成的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     #endregion11     #region 修改12     public string Set { get; set; }13     public string Update { get; set; }14     #endregion15     #region 新增16 17     public string InsertTable { get; set; }18     public string Columns { get; set; }19     public string Values { get; set; }20 21     #endregion22   }

View Code

  通过下面工具类生成完整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       else12       {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   }

View Code

  下面是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   }

View Code

  

下面是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 = _params60       };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.ParamList73       };74     }75   }

View Code

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

 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 => new11       {12         u.Id,13         u.Role.Name14       });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           else131           {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             else148             {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.Type297 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.Type318                };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   }

View Code

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