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

    1.AOP的概念 AOP(AspectOriented Programming,面向切面编程)指的是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下个程序动态统一添加功能的一种技术.AOP ...

  2. 08-hibernate注解-多对多双向外键关联

    多对多双向外键 双方持有对方的集合对象 其中一方设置: //教师类 @ManyToMany(mappedBy="teachers")   //mappedby表示教师交给学生来控制 ...

  3. Python-所有特殊方法、魔术方法、钩子

    C.__init__(self[, arg1, ...]) 构造器(带一些可选的参数) C.__new__(self[, arg1, ...]) 构造器(带一些可选的参数)通常用在设置不变数据类型的子 ...

  4. 【前端】HTML

    一.HTML介绍 Web服务本质 import socket sk = socket.socket() sk.bind(("127.0.0.1", 8080)) sk.listen ...

  5. MVC项目发布到IIS遇到的问题

    MVC4 + .NET Framework 4.5 +Windows Server 2008+ IIS7.5 + 4.0集成模式池 ,发布后可能会遇到404.0 或者403.14错误,在web.con ...

  6. Android工程:引用另一个Android工程的方法详解

    本篇文章是对在Android中引用另一个Android工程的方法进行了详细的分析介绍.需要的朋友参考下   现在已经有了一个Android工程A.我们想扩展A的功能,但是不想在A的基础上做开发,于是新 ...

  7. Atitit.设计模式-----触发器模式 trigger  详解

    Atitit.设计模式-----触发器模式 trigger  详解 1. 触发器概念1 1.1. 触发器位置 after|before|instead of1 2. 数据库里面的触发器1 2.1. o ...

  8. 动态加载图片的Adapter

    package com.example.cc.ecustapp.Adapter; import android.app.Activity;import android.content.Context; ...

  9. Cannot change version of project facet Dynamic Web Module to 3.0 requires Java 1.6 or newer 解决方案

    Eclipse Maven 开发一个 jee 项目时,编译时遇到以下错误:Description Resource Path Location TypeDynamic Web Module 3.0 r ...

  10. ext,exrReturn新增,修改删除等用

    package cn.edu.hbcf.common.vo; /** * Ext Ajax 返回对象 * * @author * @date 2012-02-21 19:30:00 * */ publ ...