輕簡級的ORM既要支持強類型編碼,又要有執行效率,還要通俗易懂給開發者友好提示,結合Expression可輕鬆定製自己所需要功能。 ...
個人覺得輕簡級的ORM既要支持強類型編碼,又要有執行效率,還要通俗易懂給開發者友好提示,結合Expression可輕鬆定製自己所需要功能。
Orm成品開源項目地址
https://github.com/PlugNT/util6
表達式解析類:
1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.Data.Common; 5 using System.Linq; 6 using System.Linq.Expressions; 7 using System.Text; 8 using System.Reflection; 9 using System.Text.RegularExpressions; 10 11 using Util.Database; 12 namespace Util.EntityMapping 13 { 14 15 16 public class SqlLmdResolver 17 { 18 19 internal int ParaIndex = 1; 20 21 22 public string _SqlWhere = null; 23 public string SqlWhere 24 { 25 get { return _SqlWhere; } 26 } 27 28 29 private List<DbParameter> _Parameters = null; 30 public List<DbParameter> Parameters 31 { 32 get { return _Parameters; } 33 } 34 35 36 private DbConfig _DbConfig = null; 37 38 39 public SqlLmdResolver(DbConfig config = null) 40 { 41 _DbConfig = config ?? DbConfig.Default; 42 _SqlWhere = string.Empty; 43 _Parameters = new List<DbParameter>(); 44 } 45 46 47 48 public void ResolveExpression(Expression expression = null, SqlWhereType whereType = SqlWhereType.And) 49 { 50 if (expression == null) 51 { 52 _SqlWhere = string.Empty; 53 return; 54 } 55 var sqlFormat = (whereType == SqlWhereType.And) ? " AND {0} " : " OR {0} "; 56 SqlLmdResolver.MemberType type = SqlLmdResolver.MemberType.None; 57 this._SqlWhere = string.Format(sqlFormat, GetResolveAll(expression, ref type).SqlConditions); 58 } 59 60 61 private enum MemberType 62 { 63 None = 0, 64 Left = 1, 65 Right = 2 66 } 67 68 private struct ParamInfo 69 { 70 public string SqlConditions; 71 public object ObjectValue; 72 } 73 74 75 76 private string AddParametersReturnLeft(ref ParamInfo left, ParamInfo right) 77 { 78 string oldLeftKey = left.SqlConditions; 79 left.SqlConditions = "P"+ ParaIndex + oldLeftKey; 80 ParaIndex++; 81 if (right.ObjectValue == null) 82 { 83 this._Parameters.Add(DbProvider.MakeParam(_DbConfig, "@" + left.SqlConditions, DBNull.Value)); 84 } 85 else 86 { 87 this._Parameters.Add(DbProvider.MakeParam(_DbConfig, "@" + left.SqlConditions, right.ObjectValue)); 88 } 89 return oldLeftKey; 90 } 91 private string AddParametersReturnRight(ParamInfo left, ref ParamInfo right) 92 { 93 string oldRightKey = right.SqlConditions; 94 right.SqlConditions = "P" + ParaIndex + oldRightKey; 95 ParaIndex++; 96 if (left.ObjectValue == null) 97 { 98 this._Parameters.Add(DbProvider.MakeParam(_DbConfig, "@" + right.SqlConditions, DBNull.Value)); 99 } 100 else 101 { 102 this._Parameters.Add(DbProvider.MakeParam(_DbConfig, "@" + right.SqlConditions, left.ObjectValue)); 103 } 104 return oldRightKey; 105 } 106 107 108 109 private string GetOperator(ExpressionType expressiontype) 110 { 111 switch (expressiontype) 112 { 113 case ExpressionType.And: 114 case ExpressionType.AndAlso: 115 return " AND "; 116 case ExpressionType.Equal: 117 return " ="; 118 case ExpressionType.GreaterThan: 119 return " >"; 120 case ExpressionType.GreaterThanOrEqual: 121 return ">="; 122 case ExpressionType.LessThan: 123 return "<"; 124 case ExpressionType.LessThanOrEqual: 125 return "<="; 126 case ExpressionType.NotEqual: 127 return "<>"; 128 case ExpressionType.Or: 129 case ExpressionType.OrElse: 130 return " OR "; 131 case ExpressionType.Add: 132 case ExpressionType.AddChecked: 133 return "+"; 134 case ExpressionType.Subtract: 135 case ExpressionType.SubtractChecked: 136 return "-"; 137 case ExpressionType.Divide: 138 return "/"; 139 case ExpressionType.Multiply: 140 case ExpressionType.MultiplyChecked: 141 return "*"; 142 default: 143 throw new Exception(string.Format("不支持{0}此種運算符查找!", expressiontype.ToString())); 144 } 145 } 146 147 148 private ParamInfo GetResolveAll(Expression exp, ref MemberType type, bool isTure = true) 149 { 150 if (exp is LambdaExpression) 151 { 152 return GetResolveLambda(exp); 153 } 154 else if (exp is BinaryExpression) 155 { 156 return GetResolveBinary(exp); 157 } 158 else if (exp is MethodCallExpression) 159 { 160 return GetResolveMethodCall(exp, ref type, isTure); 161 } 162 else if (exp is ConstantExpression) 163 { 164 return GetResolveConstant(exp, ref type); 165 } 166 else if (exp is MemberExpression) 167 { 168 return GetResolveMember(exp, ref type); 169 } 170 else if (exp is UnaryExpression) 171 { 172 return GetResolveUnary(exp, ref type); 173 } 174 return new ParamInfo(); 175 } 176 177 private ParamInfo GetResolveLambda(Expression exp) 178 { 179 LambdaExpression lambda = exp as LambdaExpression; 180 var expression = lambda.Body; 181 MemberType EleType = MemberType.None; 182 183 if (expression is UnaryExpression) 184 { 185 var me = expression as UnaryExpression; 186 if (me.Operand is MemberExpression) 187 { 188 var ime = me.Operand as MemberExpression; 189 return new ParamInfo { SqlConditions = ime.Member.Name.ToString() + "=0" }; 190 } 191 } 192 if (expression is MemberExpression) 193 { 194 var me = expression as MemberExpression; 195 return new ParamInfo { SqlConditions = me.Member.Name.ToString() + "=1" }; 196 } 197 return GetResolveAll(expression, ref EleType); 198 } 199 private ParamInfo GetResolveBinary(Expression exp) 200 { 201 var expression = exp as BinaryExpression; 202 MemberType leftType = MemberType.None; 203 MemberType rightType = MemberType.None; 204 205 var left = GetResolveAll(expression.Left, ref leftType); 206 var right = GetResolveAll(expression.Right, ref rightType); 207 var oper = GetOperator(expression.NodeType); 208 var isKeyOperValue = leftType == MemberType.Left && rightType == MemberType.Right; 209 var isValueOperKey = rightType == MemberType.Left && leftType == MemberType.Right; 210 211 if (leftType == MemberType.Left && rightType == MemberType.None) 212 { 213 if (expression.Left is UnaryExpression) 214 { 215 var me = expression.Left as UnaryExpression; 216 if (me.Operand is MemberExpression) 217 { 218 left.SqlConditions = left.SqlConditions + "=0"; 219 } 220 } 221 else if (expression.Left is MemberExpression) 222 { 223 left.SqlConditions = left.SqlConditions + "=1"; 224 } 225 } 226 if (leftType == MemberType.None && rightType == MemberType.Left) 227 { 228 if (expression.Right is UnaryExpression) 229 { 230 var me = expression.Right as UnaryExpression; 231 if (me.Operand is MemberExpression) 232 { 233 right.SqlConditions = right.SqlConditions + "=0"; 234 } 235 } 236 else if (expression.Right is MemberExpression) 237 { 238 right.SqlConditions = right.SqlConditions + "=1"; 239 } 240 } 241 242 if (isKeyOperValue & (right.ObjectValue == null) && oper.Trim() == "=") 243 { 244 var oldLeft = AddParametersReturnLeft(ref left, right); 245 return new ParamInfo { SqlConditions = string.Format(" ({0} is null) ", oldLeft) }; 246 } 247 else if (isKeyOperValue & (right.ObjectValue == null) && oper.Trim() == "<>") 248 { 249 var oldLeft = AddParametersReturnLeft(ref left, right); 250 return new ParamInfo { SqlConditions = string.Format(" ({0} is not null) ", oldLeft) }; 251 } 252 else if (isValueOperKey & (left.ObjectValue == null) && oper.Trim() == "=") 253 { 254 return new ParamInfo { SqlConditions = string.Format(" ({0} is null) ", right.SqlConditions) }; 255 } 256 else if (isValueOperKey & (left.ObjectValue == null) && oper.Trim() == "<>") 257 { 258 return new ParamInfo { SqlConditions = string.Format(" ({0} is not null) ", right.SqlConditions) }; 259 } 260 261 else if (isKeyOperValue) 262 { 263 var oldLeft = AddParametersReturnLeft(ref left, right); 264 return new ParamInfo { SqlConditions = string.Format(" ({0} {1} @{2}) ", oldLeft, oper, left.SqlConditions) }; 265 } 266 else if (isValueOperKey) 267 { 268 var oldRight = AddParametersReturnRight(left, ref right); 269 return new ParamInfo { SqlConditions = string.Format(" (@{0} {1} {2}) ", right.SqlConditions, oper, oldRight) }; 270 } 271 else if (leftType == MemberType.Right && rightType == MemberType.Right) 272 { 273 return new ParamInfo { SqlConditions = string.Format(" ('{0}' {1} '{2}') ", left.SqlConditions, oper, right.SqlConditions) }; 274 } 275 else 276 { 277 return new ParamInfo { SqlConditions = string.Format(" ({0} {1} {2}) ", left.SqlConditions, oper, right.SqlConditions) }; 278 } 279 } 280 private ParamInfo GetResolveMethodCall(Expression exp, ref MemberType type, bool isTure) 281 { 282 MethodCallExpression mce = (MethodCallExpression)exp; 283 string methodName = mce.Method.Name; 284 if (methodName == "Contains") 285 { 286 MemberType leftType = MemberType.None; 287 MemberType rightType = MemberType.None; 288 if (mce.Method.DeclaringType != typeof(string) && mce.Method.DeclaringType.GetInterface("IEnumerable") != null) 289 { 290 var left = GetResolveAll(mce.Arguments[0], ref rightType); 291 var right = GetResolveAll(mce.Object, ref leftType); 292 string oldLeftKey = left.SqlConditions; 293 294 string leftKey = "P" + ParaIndex + left.SqlConditions; 295 ParaIndex++; 296 var sqlParameterNames = ""; 297 var memberType = MemberType.Right; 298 var list = GetResolveMember(mce.Object as MemberExpression, ref memberType).ObjectValue as IEnumerable; 299 var count = 1; 300 foreach (var item in list) 301 { 302 var parameterName = leftKey + count; 303 sqlParameterNames += ",@" + parameterName; 304 if (item == null) 305 { 306 this._Parameters.Add(DbProvider.MakeParam(_DbConfig, "@" + parameterName, DBNull.Value)); 307 } 308 else 309 { 310 this._Parameters.Add(DbProvider.MakeParam(_DbConfig, "@" + parameterName, item)); 311 } 312 count++; 313 } 314 sqlParameterNames = sqlParameterNames.TrimStart(','); 315 return new ParamInfo { SqlConditions = string.Format("({0} {1} IN ({2}))", oldLeftKey, isTure == false ? " NOT " : "", sqlParameterNames) }; 316 } 317 else 318 { 319 var left = GetResolveAll(mce.Object, ref leftType); 320 var right = GetResolveAll(mce.Arguments[0], ref rightType); 321 var oldLeft = AddParametersReturnLeft(ref left, right); 322 return new ParamInfo { SqlConditions = string.Format("({0} {1} LIKE '%'+@{2}+'%')", oldLeft, isTure == false ? " NOT " : "", left.SqlConditions) }; 323 } 324 } 325 else if (methodName == "StartsWith") 326 { 327 MemberType leftType = MemberType.None; 328 MemberType rightType = MemberType.None; 329 var left = GetResolveAll(mce.Object, ref leftType); 330 var right = GetResolveAll(mce.Arguments[0], ref rightType); 331 var oldLeft = AddParametersReturnLeft(ref left, right); 332 return new ParamInfo { SqlConditions = string.Format("({0} {1} LIKE @{2}+'%')", oldLeft, isTure == false ? " NOT " : "", left.SqlConditions) }; 333 } 334 else if (methodName == "EndWith") 335 { 336 MemberType leftType = MemberType.None; 337 MemberType rightType = MemberType.None; 338 var left = GetResolveAll(mce.Object, ref leftType); 339 var right = GetResolveAll(mce.Arguments[0], ref rightType); 340 var oldLeft = AddParametersReturnLeft(ref left, right); 341 return new ParamInfo { SqlConditions = string.Format("({0} {1} LIKE '%'+@{2})", oldLeft, isTure == false ? " NOT " : "", left.SqlConditions) }; 342 } 343 else if (methodName == "ToString") 344 { 345 type = MemberType.Right; 346 return GetResolveAll(mce.Object, ref type); 347 } 348 else if (methodName.StartsWith("To")) 349 { 350 type = MemberType.Right; 351 return GetResolveAll(mce.Arguments[0], ref type); 352 } 353 return new ParamInfo(); 354 } 355 356 private ParamInfo GetResolveConstant(Expression exp, ref MemberType type) 357 { 358 type = MemberType.Right; 359 ConstantExpression ce = ((ConstantExpression)exp); 360 if (ce.Value == null) 361 { 362 return new ParamInfo(); 363 } 364 else 365 { 366 return new ParamInfo { ObjectValue = ce.Value }; 367 } 368 } 369 private ParamInfo GetResolveUnary(Expression exp, ref MemberType type) 370 { 371 UnaryExpression ue = ((UnaryExpression)exp); 372 var mex = ue.Operand; 373 return GetResolveAll(mex, ref type, false); 374 } 375 376 private ParamInfo GetResolveMemberMethod(MemberExpression exp) 377 { 378 var proInfo = exp.Member as System.Reflection.PropertyInfo; 379 if (proInfo != null) 380 { 381 object dynInv = proInfo.GetValue(null, null); 382 return new ParamInfo { ObjectValue = dynInv }; 383 } 384 else 385 { 386 var fieInfo = exp.Member as System.Reflection.FieldInfo; 387 if (fieInfo != null) 388 { 389 object dynInv = fieInfo.GetValue(null); 390 return new ParamInfo { ObjectValue = dynInv }; 391 } 392 }