上一节中鄙人通过解析表达式树生成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 }

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

自己动手写ORM(02):Sql生成器实现的更多相关文章

  1. 自己动手写ORM的感受

    之前看到奋斗前辈和时不我待前辈的自己动手写ORM系列博客,感觉讲解的通俗易懂,清晰透彻.作为一个菜鸟,闲来也想着自己写一个ORM,一来加深自己对 ORM的理解,以求对EF,NHibernate等ROM ...

  2. (新)自己动手写ORM框架(1)-增删查改的使用

    之前写过一个系列文章自己动手写ORM框架,经过在多个项目的中的使用,对这套代码进行了许多改进,下面是使用方法: 新增学员信息代码预览: DBHelper db = DBHelper.getInstan ...

  3. 自己动手写ORM(01):解析表达式树生成Sql碎片

     在EF中,我们查询数据时可能会用拉姆达表达式 Where(Func<T,ture> func)这个方法来筛选数据,例如,我们定义一个User实体类 public class User { ...

  4. 自己动手写ORM框架

    提起ORM框架,大家都很熟悉,网上流行的ORM框架有很多,其中出名的有一些,不出名的更是数不胜数. 下面是自己实现的一个简单的ORM框架,实现了常用的增删查改功能,供大家研究ORM实现原理. 功能描述 ...

  5. 自己动手写ORM

    http://blog.csdn.net/sundacheng1989/article/category/1350100

  6. Python - 动手写个ORM

    Python - 动手写个ORM 任务: 模拟简单的ORM - Object Relational Mapping 为model添加create方法 代码很简单,直接上 字段类型类 class Fie ...

  7. 自己动手写SQL执行引擎

    自己动手写SQL执行引擎 前言 在阅读了大量关于数据库的资料后,笔者情不自禁产生了一个造数据库轮子的想法.来验证一下自己对于数据库底层原理的掌握是否牢靠.在笔者的github中给这个database起 ...

  8. 为初学者写ORM,ORM的原理及测试案例

    提纲 一.什么是ORM.二.反射以及Attribute在ORM中的应用.三.创建一个数据库表和表对应的实体model.四.实体model如何映射出数据库表.五.组合ORM映射生成insert语句.六. ...

  9. 自己动手实现mybatis动态sql

    发现要坚持写博客真的是一件很困难的事情,各种原因都会导致顾不上博客.本来打算写自己动手实现orm,看看时间,还是先实现一个动态sql,下次有时间再补上orm完整的实现吧. 用过mybatis的人,估计 ...

随机推荐

  1. Firefly 性能测试 通报

    http://bbs.gameres.com/forum.php?mod=viewthread&tid=220516 Firefly 性能测试 主要考虑点 网络IO的并发 进程间通信压力 数据 ...

  2. 数据库连接dbcp$c3p0

    <?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <!-- 这是默认配置信 ...

  3. VUE 数组更新

    1.数据方法分类: (1)原数组改变 push pop unshift shift reverse sort splice (2)原数组未变,生成新数组 slice concat filter map ...

  4. Cannot make a static reference to the non-static method的解决方法

    报错原因:在一个类中写了一个public String getContent()方法和一个main()方法,getContent()方法中包含了getClass()方法,在main()方法中直接调用了 ...

  5. 如何取得jvm实例的cpu占用(转)

    时间 2014-08-29 17:11:34 田加国的博客 原文  http://www.tianjiaguo.com/programming-language/java-language/如何取得j ...

  6. Spring集成Redis集群(含spring集成redis代码)

    代码地址如下:http://www.demodashi.com/demo/11458.html 一.准备工作 安装 Redis 集群 安装参考: http://blog.csdn.net/zk6738 ...

  7. ubuntu安装Skype 4.3

    Install Skype 4.3 Step 1: Remove previous version sudo apt-get remove skype skype-bin:i386 skype:i38 ...

  8. 多校第九场Arithmetic Sequence题解

    题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=5400 题意:给定等差数列的差值d1,d2.问长度为n的数列中有多少个满足条件的子序列,条件为子序列中 ...

  9. Wpf ScrollBar自定义样式

    Wpf的ScrollBar可以分为六个区域:A.背景.B.向上按钮.C.向下的按钮.D.Track里面向上的按钮.E.Track里面向下的按钮.F.Track的Thumb 详情见下图 下面通过一个例子 ...

  10. Web前端的状态管理(State Management)

    背景 我相信很多朋友跟我一样,初次听到什么Flux, Redux, Vuex,状态管理的时候是一脸懵逼的.因为在外面之前前端大部分开发的时候,根本没有那么多的概念.自从ReactJS火爆后,什么Flu ...