这个ExpressionHelper类,是整个SqlHelper中,最核心的一个类,主要功能就是将Lambda表达式转换为Sql语句。同时这个转换过程比较复杂,所以下面详细讲解一下思路和这个类的作用。

0x01基本

在Sql语句中,主要由表名,字段,条件语句等元素组成,而这些元素中,表名,字段可以由实体表示出来,条件语句可以由Lambda表达式表现出来。

在Sql语句中,条件语句可以说是Select中的核心,其中很多功能和Lambda中提供的方法很相似,比如:

实体:

aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAARcAAAD+CAIAAACfjdZ9AAATHElEQVR4nO2dTW7byBaFs4Z+QNCzDBryKAI8drfjUZJGgJZGghciDwQthADhYdZAUAvwEsiFcAdvQLJYP7f4U2RRVbyn8aFhM1KZ5OHhvSy5jj+9vPwAAMzh08vLj8+f//z8+c/9/nHqF1++/OXwrvqLL1/+cvuh+CKQL1gp2H+pNy7a7x8deHn54fbGme8FIcBKwf6DhYuAI6wUHHbRXc4jKw02CSsFUYuAF1gpCBcBL7BSEB0d8AIrBVGLgBdYKRiji655VaYn+9tP72VVVdXtsn+85FV+uf9ZZgih4Ok9T1/3+9e0vF32j6e0zC+P+8utyq/ay8r8ut8/XvLK/K9R83Kr2mvgkouLQbowLjf9neX7qflZzQ74PViJADu6K3VuqzJ93e8fT2lZtf5p9KgWPl9gJKSCp7TML69peUvTUkim3+Y6F+n3SvmeeErLqnw/dS+75lVVptdT95ZrXqsvjHofF13DqkW1SYiTXr6fui3iHL02njLMBlbAVPBk6JFf1Hti+Z5239/ynlokYZqtJQQXXfPqFpCLjHvPY3NeOguZtlFOFrq7NbGpf0lveVnVqglNuyt+31eLmhHIbkS5V17NG2hVVXm+rosut/oKDLCjq894lV8eL3mlt9SKHte07RnK9NUoWcAvlIKvaVnVHd3lcivTa5rf8vqCltUxXURrV7dwr42pzCtBvOsutah5OK+qqgqoFsnQrV1N81jZ3cZObQsO1sRUsHVFfRG/pnldjm7p6XF/uXUa1def0t3JheaWl0qj0c1SdEWnmZxoxtQnMNZ9Ljq9B+ciWzVvNXhtb2/XvJ2TOaVlXeLRzq2JRcHXtFT7tMutyq9ts9325E3F6K9FDXTjJzun+7p9DFu6K+m71C+3gDq62j9lSRWW9k7WGqbp6OrWrq1FQ/PjYFFsCkp3vvpSfk1L9bJuOrprXt1S/fmmTE/EpJHlltpBzAR6Plj5qCfXoqen5zFDO+8W3Z61Lrrkt4toGNri071FmYoAfrE8KnTTp+1lfc0rykWn97J8v6hXP1F2LreqLMnPM/omIVarRaf3cuoc3dPT869f/w0PPWO3zNlS4/ajd714LroLFgWlqe38Wj/M5Bd5sq5xUf1UY8itTs92fqiHtT7t3KcWnd7LqkxPU+bo/vnn269f/63gop5atN8/Ki5qnzjxRLQ+lo5Os4F03V9uYkahTN/zdircqEVtR2eZtasqeQZipXJkOdjm6MbWImEh3y4CscBKwQV+j062EFwEalgpOPf36DQLwUWghpWCs2qRaSG4CNSwUtDdRaSF4CJQw0rB6FZGgDhgpWCMq/RABLBSEC4CXmCl4LCLAABzmFuLdrsHN+a8F4QAKwX7DxYuAo6wUnDYRXOaRWjAFlYKohYBL7BSEC4CXmClIDo64AVWCm6xFh2SoiqSA/mvb1mVne990jmgKNinyBa4m4u+ft0/Pf39/Pzt+fnb09PfX7/ux+/WADNcdM6qIjnudg+73TEp5FVd8N404CKBr47u69f99+8/fv/+/fHx8fHx8fv37+/ff8hGmu6iY1JU2XnwZdNc1A14zqpqzPigYYqCI7ULlzVqUV1wNISFhJGenv520mCSEq4u2tU3VFSkscBFgsVc9GH57+fPf3/+/Lf++vn5m3W3Dl171Z7u+tS/ZVVVFUXXfBXJQbnc37LuX46qi7R/etj1uyh+se92YXWKvGVVkSSZqoik3b13e4GDNVimo5vtomOStef3nLWPKPVzi7CEdIkrmnUO2TVbJDkP+nvhIi8XlqpIlb21G2sJoj+x63V0tU/q/zt0dEo12pmnnnLROTNub62Lzt0dUC5HQy7a8iOyxwtLq0XdzQsumjK7oLlo2uzCISlESen0mO0iqn/oc5HlLYAELhIsNkenTS3sJs10S5fvISkm1KLdW9Y9R70lynOR/E8P56zpDHvn6FCIJgAXCQL51LX76KbIMkstals+bXahawSFiuY/yXayfF6EKjRHwQEXSdrde7cXOFiDQFwE4oOVgvg9OuAFVgqiFgEvsFIQLgJeYKUgOjrgBVYKohYBL7BSEC4CXmCl4LCLAABzQC0CjrBSsP9g4SLgCCsFh12EOTrgACsFUYuAF1gpCBcBL7BSEB0d8AIrBVGLgBcUBZGkBRf1gPw6G3CRIK6O7g5LJpFfZ2OKgljrChchv44CLhKE4yIjO05f723GmhFxc9LGIknkNBLp7Xo6Vx15l2WFNE4bBYHkrVEKIo8ugI7OjJWzJtSJrBIqbk5OLDnWwUIHc3xb5J0UonLOkF83RUHk0d2/FlkirPoS6si4OW0c8a0+vhhHU1c4s4tAQX7dKAWRARSiiwYT6kjjTXARre4hKYrkeEiK5m6K/LqRCsJFgXR0SqzccEIdGTc3uqNrtlMTBkWWSRUG+XWjFISL7l+LdmasHJlQp8aaUXFz0sbxswvKjjXukL5Fft2wgsijC8JFPnDquCTbgD5i+dx8hYMNpKNbimNSKH92ZbIfeH8ENAm4SLC5WiS1eVMtVE/7Rd2+rwlcJNici8BasFKQVUcH1oOVgqhFwAusFISLgBdYKTjsIgDAHFCLgCOsFOw/WLgIOMJKwWEXYY4OOMBKQdQi4AVWCsJFwAusFERHB7zASsEt1qK+3KZumeq80aaPwww/LpIXVgQEXNRhLDOvquwNLnIjQBd1i5TPUrDNQfpXWXfLRnJpzGY6upHrJcdc/bbXaGtp4aI+gnPRISnE0ubCjL6h7UFtJOI0NlOL4KKwCM1FIrbJNiD5Avpd50wUqzEHG4yLiOXfclhc0dXdIjkoa+m0VDr56icD6x50hzSjabFpY8ZhjaTgMZGi/JoGeVhTMlRQibPrLuXhoSx5THpqGhEZYGyUy5rlclUJpKOzps/RGQlq+pnFIWRgnfYabTSyFvWMwxpFQSIQZoympHxUnN2ooYzeoQm+0fe887l1oz5aJLWoP31O+1Zc90SyQnv8ZGAdeY76XdQ3DmtUBdt7jbrkfkBTWj4i/GR4KKN6NFls1ikocj6J/tHGweqE4aLB9Dnt25EuskaXTHRRtMk1XtHUrx/T60C/sZqOdNGoy0PR9JxV2oONcQH0u2h6Lbp/RzecPvfQ09EpQXZKJ2YG1lHnaLijs43DGuLJVo7yG6UpKZ/horFDtW+kI2iOByljUPSf1EZihBhqEZ0+RwSXErMLepCd5BAysE57jXrKpNi0MeOwxlD/mBRyBRilKSUfHQo5OFQ322Y04SJNWjTlB2Mn9VTdKOfoQGwEp6DxaOSK0+dF9+/oQIQEqKAcsO6M4+8uoBYBB1gpCBcBL7BSEB0d8AIrBVGLgBdYKQgXAS+wUnDYRQCAOaAWAUdYKdh/sHARcISVgsMuwhwdcICVgqhFwAusFISLgBdYKYiODniBlYJbrEXL5tH5oG8PxX6GGLw2Hj8uCvS0wEXka8TSk7m/Ajx9D8U+hHi5jCdAFyGPbpCFkrTOmbLY7pzdKUeBvFxiSkcJzkXIoxvBIi5Sln/fFbho/GkZBfLo1sqjG4g0kZYY74x9UNcedzewZkw1Ho3ewyJJxA6YwWtaIN7iF+jCSAoijy6Ijm6tPDqri9RxbPsgtkvjtDcz9ZV0vsqxSXcSV48ZvBZpLUIeXRC1aJ08OpuL9O3SpUDvg7CoON1GPBq5h2e1FlExHVG6CHl093fRenl0lrabcBF5WXff1sFr0kJ/5i5CHt3dO7oV8+j0W1QzR2d0dFJ/os6KSj2bHL9mc1FfR7cpFyGP7t61aOU8OrnZ6+5Y9tmFLDO2G+fd6iJ5N4zZBaN/kALxVrXEbAUftDsO8ujCnOm+C33Fgfz8YYAN5RUHpyDy6ELF7iK6bSBH6JmSipgAFUQeXZjQLqpbhrEPMAe5a9iIhXbRKLjGwcJFwBFWCqKjA15gpSBqEfACKwXhIuAFVgoOuwgAMAfUIuAIKwX7DxYuAo6wUnDYRZijAw6wUhC1CHiBlYJwEfACKwXR0QEvsFJwi7Uo/Dw6BvQpuOCvrg9nkt37YPm5SE6r0NcLgUnARYKIOrpFkrSMFcsDv5od0+LTlZnhosGzGtxp30wt8uCi3eAyoeDkDAe4SBCMi9bJoyPk0eIc5H0wA+LMAfliqP+mLNRWMgwmnVX1BUqCRZGcm9GaXDRdC18CRdHRrZVH1+ci6z6IeA1qQL6oCmpZMV08iNNZtWrdDNssk3wzXuBLoEhq0Tp5dLSLxoWe0QOud9WGhqKgNTDM7azaXCQnXRlf+xQoBhetl0dnuEi8bHAfNhQ8sgijXOR4Vl1d5E2gGDq69fLozDm68flpdMAdW+wdnRS753hWnVzkU6AYatF6eXTq50VGqrCxD2pAnC3gjiW6+vKfDOpi9xzPKqX1oIs8ChSFi0B8sFIwho4ORAgrBVGLgBdYKQgXAS+wUhAdHfACKwVRi4AXWCkIFwEvsFJw2EUAgDmgFgFHWCnYf7BwEXCElYLDLsIcHXCAlYKoRcALrBSEi4AXWCmIjg54gZWCW6xFy+fRYQX4ZPy4SF7yEBBwkckxKSr1j1HDRZMJ0EXG3xjXYjlEton8I/SNjn9jPJKObpEkrYfd7mF3SIqiUAO0xrtovt824tjgXHRICnXFeL1mT45/ar5Wc1Sojfo+bKYWLeaiQ1IUyfGcWZajL7MbXkcIgtBcpAramCoRhUVJX2slIDfuHnbnTK1psbhopTy6h+5Oo4RdSD+LXLrcrEjXstTkPexZUv6mrqUm16vHh6SgdEevz5j1bBhnjJBPOkniUh4eSisgjSW69kw1RrOd3LgjyloUHd1qeXSyefQXdD9L7AORnCpXEmMPiaMw93CLteisBC305/tV6m3OkE8OmqsFGjlUp5Twg/hCe2Sqt5MbzdGMy1UnmFq0Uh6d8uwofW37WfWdkrjJUe+ijoLYwy26SNyS1PvOgKa0fPKtbVxU4E6tHtKwjrXIeDSKwUXr5dG96d4a/Fntt5W4L9pcRB4FFxd1d3fpDAxpOtJFoy4PUT20PwvSNs9EA0929dpo9MFqhNHRrZZH1/UD4mS17Yc0993twyFJdMPYXUQfhbmH23TR7pAURZaJW/goTUn5DBeNHYqYlqDbDaL/VB1ldPIx1KK18ujOmfYxkdhyTIoqy6TJBfkF6pOulKVGliztKMw9VNPYosVQX/sUbpSmlHxmRzdqKH2Ort3YPXcZQlg3xjpHB2IjOAWNiTVXnD4vun9HByIkQAWN311wwfF3F1CLgAOsFISLgBdYKYiODniBlYKoRcALrBSEi4AXWCk47CIAwBxQi4AjrBTsP1i4CDjCSsFhF2GODjjASkHUIuAFVgrCRcALrBRERwe8wErBLdai5fPoFqVv97YDXCTg6SJpxevsXwGeuHvbAS4SRNTRLZSkdc4qaQ3s7pyZvwa/0J5sHFVBh3MS02ncTC1axEXKMnJXYpLfH3CRIBgXrZNHR0ea6C9W85m6eLR2fGlPyD1XYiG0t9//gvBwYRnnxDjzUl5CvUo/M94SNFF0dGvl0VldpI6jpskR8WhygIm55+ruGW/fCPZaRCcBduFVZnJI8ERSi9bJo7O5SN8u59HRYRpErIrYc60WUelqG8DqIksSoBHuBxct66JV8+ioS5lwUf2yIReRew4X2Qv+Zl10/45utTy6Znzpam7m6IyOjk4hNlxE7jlzF1nOfBfqi47O13PRKnl0DXLL0X1eZJ9dMGygRdLpe87RRWrIHpkEKJmnPu0R5fJF4SIQH6wUjKGjAxHCSkHUIuAFVgrCRcALrBRERwe8wEpB1CLgBVYKwkXAC6wUHHYRAGAOqEXAEVYK9h8sXAQcYaXgsIswRwccYKUgahHwAisF4SLgBVYKoqMDXmClIGoR8IKi4ObWw/cdrMEGXST9jehu8Y+6aggsAFwk2GBHp7lIjp7Tl+uBGUxRMKZlrQ4Hu/1apIinRHCBWcBFgjBcpK8AlzMSzCXcWrKMHFuXHPpdFL+c4WBRcESCX4TE0NGRLiLqBhl0psXWwUUrYXdRf4JflMRbi7TgJVvQma7QkIu2/BC8Jn21aCjBLzridZFQovUSHXQ2xUV9CcNgEQW5uiiMjk4OqWo6ukQJ7H6wBJ2NdlGT5nR/SbYBXCQIoxZJEwlSHt1D18GJ1DhrKH43lPXzIlShRZniopii54YP1iAUF4HoYKVgDB0diBBWCqIWAS+wUhAuAl5gpSA6OuAFVgqiFgEvsFIQLgJeYKXgsIsAAHNALQKOsFKw/2DhIuAIKwWHXYQ5OuAAKwVRi4AXWCkIFwEvsFIQHR3wAisFUYuAF1gpCBcBL7BSEB0d8AIrBVGLgBdYKQgXAS+wUhAdHfACKwVRi4AXWCkIFwEvsFIQHR3wAisFUYuAF1gpCBcBL7BSEB0d8AIrBVGLgBdYKQgXAS+wUhAdHfACKwVRi4AXWCkIFwEvsFJw2EUAgDl8enn58ccf/7u71wGIF7gIgLl8euHU3QLgA9QiAOYCFwEwF3R0AMwFtQiAucBFAMwFHR0Ac/k/6/JB7FoGp+EAAAAASUVORK5CYII=" alt="" />

     [TableName("RA_MyBlog_Article")]
public class ArticleEntity
{
[Primary]
[Identity]
//文章ID
public int articleID { get; set; }
//分类ID
public int categoryID { get; set; }
//文章标题
public string articleTitle { get; set; }
//文章版权
public string articleCopyright { get; set; }
//文章创建时间
public DateTime articleDate { get; set; }
//文章摘要
public string articleAbstract { get; set; }
//文章内容
public string articleContain { get; set; }
//文章所属User
public int userID { get; set; }
}
Lambda表达式 Sql表达式
GetList<ArticleEntity>(a=>a.articleID > 1 && a.userID = 1) Select * From RA_MyBlog_Article Where articleID > 1 And userID = 1
GetList<ArticleEntity>(a=>list.Contains(a.articleID)) Select * From RA_MyBlog_Article Where articleID In [list中的元素]
Join<UserEntity,ArticleEntity>((a,b)=>a.UserID == b.UserID) Select * From RA_MyBlog_Article,RA_MyBlog_User Join RA_MyBlog_User On (RA_MyBlog_Article.UserID = RA_MyBlog_User.UserID )

从上表可以看出,由Lambda表达式转换为Sql表达式是完全可能的。

0x02 Lambda表达式

Lambda设计到的内容比较多,大家有兴趣可以去百度找一下这方面的介绍,这里只介绍一些涉及到的部分:

以上面的表达式GetList<ArticleEntity>(a=>a.articleID > 1 && a.userID = 1)为例,其中a=>a.articleID > 1 && a.userID = 1这部分是我们需要的部分。在C#中,由Expression对象负责对Lambda表达式的解析和处理。Expression的子类有很多,分布在System.Linq.Expressions命名空间下,这里用到的有

UnaryExpression:一元表达式,比如取反'!'

ConstantExpression:常量表达式,比如1

MemberExpression:成员表达式,一般为变量,比如a.articleID

MethodCallExpression:函数表达式,比如Contains()

BinaryExpression:二元表达式,比如a.articleID > 1

对于这个例子:a.articleID > 1 && a.userID = 1,整体是一个与类型的二元表达式,左元素为a.articleID > 1,是一个Larger类型的二元表达式,其中左元素是成员表达式,右元素是常量表达式。右元素为a.userID = 1,是一个相等类型的二元表达式,其中左元素是成员表达式,右元素是常量表达式。

2.用到的枚举,没啥可说的,包含了Lambda表达式中常见的元素类型。

 namespace RA.DataAccess.Enumerations
{
public enum EnumNodeType
{
[Description("二元运算符")]
BinaryOperator = ,
[Description("一元运算符")]
UndryOperator = ,
[Description("常量表达式")]
Constant = ,
[Description("成员(变量)")]
MemberAccess = ,
[Description("函数")]
Call = ,
[Description("未知")]
Unknown = -,
[Description("不支持")]
NotSupported = -
}
}

0x03 功能部分

1.判断表达式类型

         /// <summary>
/// 判断表达式类型
/// </summary>
/// <param name="func">lambda表达式</param>
/// <returns></returns>
private static EnumNodeType CheckExpressionType(Expression func)
{
switch (func.NodeType)
{
case ExpressionType.AndAlso:
case ExpressionType.OrElse:
case ExpressionType.Equal:
case ExpressionType.GreaterThanOrEqual:
case ExpressionType.LessThanOrEqual:
case ExpressionType.GreaterThan:
case ExpressionType.LessThan:
case ExpressionType.NotEqual:
return EnumNodeType.BinaryOperator;
case ExpressionType.Constant:
return EnumNodeType.Constant;
case ExpressionType.MemberAccess:
return EnumNodeType.MemberAccess;
case ExpressionType.Call:
return EnumNodeType.Call;
case ExpressionType.Not:
case ExpressionType.Convert:
return EnumNodeType.UndryOperator;
default:
return EnumNodeType.Unknown;
}
}

2.判断一元表达式:

         /// <summary>
/// 判断一元表达式
/// </summary>
/// <param name="func"></param>
/// <returns></returns>
private static string VisitUnaryExpression(UnaryExpression func)
{
var result = ExpressionTypeToString(func.NodeType);
var funcType = CheckExpressionType(func.Operand);
switch (funcType)
{
case EnumNodeType.BinaryOperator:
return result + VisitBinaryExpression(func.Operand as BinaryExpression);
case EnumNodeType.Constant:
return result + VisitConstantExpression(func.Operand as ConstantExpression);
case EnumNodeType.Call:
return result + VisitMethodCallExpression(func.Operand as MethodCallExpression);
case EnumNodeType.UndryOperator:
return result + VisitUnaryExpression(func.Operand as UnaryExpression);
case EnumNodeType.MemberAccess:
return result + VisitMemberAccessExpression(func.Operand as MemberExpression);
default:
throw new NotSupportedException("不支持的操作在一元操作处理中:" + funcType.GetDescription());
}
}

3.判断常量表达式:

         /// <summary>
/// 判断常量表达式
/// </summary>
/// <param name="func"></param>
/// <returns></returns>
private static string VisitConstantExpression(ConstantExpression func)
{
if (func.Value.ToString() == "")
{
return "\'\' ";
}
else if (func.Value.ToString() == "True")
{
return "1 = 1 ";
}
else if (func.Value.ToString() == "False")
{
return "0 = 1 ";
}
else
{
return "'" + func.Value.ToString() + "' "; }
}

4.判断变量表达式

         /// <summary>
/// 判断包含变量的表达式
/// </summary>
/// <param name="func"></param>
/// <returns></returns>
private static string VisitMemberAccessExpression(MemberExpression func)
{
try
{
var tablename = EntityHelper.GetTableName(func.Expression.Type);
return tablename + "." + func.Member.Name + " ";
}catch
{
object value;
switch (func.Type.Name)
{
case "Int32":
{
var getter = Expression.Lambda<Func<int>>(func).Compile();
value = getter();
}
break;
case "String":
{
var getter = Expression.Lambda<Func<string>>(func).Compile();
value = "'" + getter() + "'";
}
break;
case "DateTime":
{
var getter = Expression.Lambda<Func<DateTime>>(func).Compile();
value = "'" + getter() + "'";
}
break;
default:
{
var getter = Expression.Lambda<Func<object>>(func).Compile();
value = getter();
}
break;
}
return value.ToString();
}
}

5.判断函数表达式:为了演示,此处这个表达式只支持Contains()函数,其他的函数可以按需添加。

         /// <summary>
/// 判断包含函数的表达式
/// </summary>
/// <param name="func"></param>
/// <returns></returns>
private static String VisitMethodCallExpression(MethodCallExpression func)
{
if (func.Method.Name.Contains("Contains"))
{
//获得调用者的内容元素
var getter = Expression.Lambda<Func<object>>(func.Object).Compile();
var data = getter() as IEnumerable;
//获得字段
var caller = func.Arguments[];
while (caller.NodeType == ExpressionType.Call)
{
caller = (caller as MethodCallExpression).Object;
}
var field = VisitMemberAccessExpression(caller as MemberExpression);
var list = (from object i in data select "'" + i + "'").ToList();
return field + " IN (" + string.Join(",", list.Cast<string>().ToArray()) + ") ";
}
else
{
throw new NotSupportedException("不支持的函数操作:" + func.Method.Name);
}
}

6.判断二元表达式:二元表达式一般由其他表达式组成,有时还会有嵌套的情况,所以此处使用递归来解析。

         /// <summary>
/// 判断包含二元运算符的表达式
/// </summary>
/// <remarks>注意,这个函数使用了递归,修改时注意不要修改了代码顺序和逻辑</remarks>
/// <param name="func"></param>
private static string VisitBinaryExpression(BinaryExpression func)
{
var result = "(";
var leftType = CheckExpressionType(func.Left);
switch (leftType)
{
case EnumNodeType.BinaryOperator:
result += VisitBinaryExpression(func.Left as BinaryExpression);break;
case EnumNodeType.Constant:
result += VisitConstantExpression(func.Left as ConstantExpression);break;
case EnumNodeType.MemberAccess:
result += VisitMemberAccessExpression(func.Left as MemberExpression);break;
case EnumNodeType.UndryOperator:
result += VisitUnaryExpression(func.Left as UnaryExpression);break;
case EnumNodeType.Call:
result += VisitMethodCallExpression(func.Left as MethodCallExpression);break;
default:
throw new NotSupportedException("不支持的操作在二元操作处理中:" + leftType.GetDescription());
} result += ExpressionTypeToString(func.NodeType) + " "; var rightType = CheckExpressionType(func.Right);
switch (rightType)
{
case EnumNodeType.BinaryOperator:
result += VisitBinaryExpression(func.Right as BinaryExpression); break;
case EnumNodeType.Constant:
result += VisitConstantExpression(func.Right as ConstantExpression); break;
case EnumNodeType.MemberAccess:
result += VisitMemberAccessExpression(func.Right as MemberExpression); break;
case EnumNodeType.UndryOperator:
result += VisitUnaryExpression(func.Right as UnaryExpression); break;
case EnumNodeType.Call:
result += VisitMethodCallExpression(func.Right as MethodCallExpression); break;
default:
throw new NotSupportedException("不支持的操作在二元操作处理中:" + rightType.GetDescription());
} result += ") ";
return result;
}

7.将Lambda表达式转换为Sql语句。整个类的入口点:

         /// <summary>
/// 通过Lambda解析为Sql
/// </summary>
/// <param name="func"></param>
/// <returns></returns>
public static string GetSqlByExpression(Expression func)
{
var funcType = CheckExpressionType(func);
switch (funcType)
{
case EnumNodeType.BinaryOperator:
return FormatSqlExpression(VisitBinaryExpression(func as BinaryExpression));
case EnumNodeType.Constant:
return FormatSqlExpression(VisitConstantExpression(func as ConstantExpression));
case EnumNodeType.Call:
return FormatSqlExpression(VisitMethodCallExpression(func as MethodCallExpression));
case EnumNodeType.UndryOperator:
return FormatSqlExpression(VisitUnaryExpression(func as UnaryExpression));
case EnumNodeType.MemberAccess:
return FormatSqlExpression(VisitMemberAccessExpression(func as MemberExpression));
default:
throw new NotSupportedException("不支持的操作在表达式处理中:" + funcType.GetDescription());
}
}

SqlHelper简单实现(通过Expression和反射)5.Lambda表达式解析类的更多相关文章

  1. 基类的参考Expression能传一个lambda表达式

    using System;using System.Collections.Generic;using System.Data.Entity.Infrastructure;using System.L ...

  2. SqlHelper简单实现(通过Expression和反射)7.MySql数据处理类

    MySql的数据处理类和Sql Server没有太大差别,从思路上来说没有区别,所以此处只是给出代码,不再多加解释了. using System; using System.Configuration ...

  3. SqlHelper简单实现(通过Expression和反射)1.引言

    之前老大说要改变代码中充斥着各种Select的Sql语句字符串的情况,让我尝试着做一个简单的SqlHelper,要具有以下功能: 1.不要在业务代码中暴露DataTable或者DataSet类型: 2 ...

  4. SqlHelper简单实现(通过Expression和反射)6.Providor模式(工厂+策略)可配置数据库选择

    基本思想,将MsSqlDbUtility和MySqlDbUtility设计成单例模式,通过App.config或Web.config进行默认的数据库设置,然后通过DbUtilityFactory获取D ...

  5. 程序猿修仙之路--数据结构之你是否真的懂数组? c#socket TCP同步网络通信 用lambda表达式树替代反射 ASP.NET MVC如何做一个简单的非法登录拦截

    程序猿修仙之路--数据结构之你是否真的懂数组?   数据结构 但凡IT江湖侠士,算法与数据结构为必修之课.早有前辈已经明确指出:程序=算法+数据结构  .要想在之后的江湖历练中通关,数据结构必不可少. ...

  6. 利用表达式树Expression优化反射性能

    最近做了一个.Net Core环境下,基于NPOI的Excel导入导出以及Word操作的服务封装,涉及到大量反射操作,在性能优化过程中使用到了表达式树,记录一下. Excel导入是相对比较麻烦的一块, ...

  7. 反射调用与Lambda表达式调用

    想调用一个方法很容易,直接代码调用就行,这人人都会.其次呢,还可以使用反射.不过通过反射调用的性能会远远低于直接调用——至少从绝对时间上来看的确是这样.虽然这是个众所周知的现象,我们还是来写个程序来验 ...

  8. 用lambda表达式树替代反射

    本节重点不讲反射机制,而是讲lambda表达式树来替代反射中常用的获取属性和方法,来达到相同的效果但却比反射高效. 每个人都知道,用反射调用一个方法或者对属性执行SetValue和GetValue操作 ...

  9. 委托、匿名委托、Lambda 表达式、Expression表达式树之刨根问底

    本篇不是对标题所述之概念的入门文章,重点在阐述它们的异同点和应用场景.各位看官,这里就不啰嗦了,直接上代码. 首先定义一个泛型委托类型,如下: public delegate T Function&l ...

随机推荐

  1. Temporal Ensembling for Semi-Supervised Learning

    Laine, Samuli, and Timo Aila. "Temporal Ensembling for Semi-Supervised Learning." arXiv pr ...

  2. 解决java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver问题

    今天在做项目的时候突然遇到解决java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver问题,知道是j ...

  3. requirejs学习(一)

    requirejs学习(一) 随着网站功能逐渐丰富,网页中的js也变得越来越复杂和臃肿,各种依赖(插件等)也逐渐增多,原有通过script标签来导入一个个的js文件这种方式已经不能满足现在的需求,我们 ...

  4. jquery js 动态加载 js文件

    jquery方法 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://ww ...

  5. 【PyQt】算法-插入、递归、冒泡

    # coding=utf-8 import sys from PyQt4.QtGui import * from PyQt4.QtCore import * class MainWindow(QMai ...

  6. 在ChemDraw中输入千分号的方法

    很多的用户都会使用ChemDraw化学绘图工具来绘制一些化学反应的过程,但是一些化合物中有些元素所占的比例是非常小的,这个时候往往就需要千分号来显示比例.但是在ChemDraw的工具栏上只有百分号没有 ...

  7. 手动编译svn

    #!/bin/bash yum -y remove subversionmkdir -p /dist/{dist,src}cd /dist/dist/bin/rm -f openssl* subver ...

  8. Laravel5.1 模型 --多态关联

    什么是多态关联? 一个例子你就明白了:好比如说评论 它可以属于视频类 也可以属于文章类,当有个需求是 从评论表中取到视频类的数据,这就需要用到多态关联了. 简单的一句话总结:一张表对应两张表. 1 实 ...

  9. iOS-setNeedsLayout等布局方法

    列举下iOS layout的相关方法: layoutSubviews layoutIfNeeded setNeedsLayout setNeedsDisplay drawRect sizeThatFi ...

  10. 简述synchronized和java.util.concurrent.locks.Lock异同

    主要相同点:Lock能完成synchronized所实现的所有功能.主要不同点:Lock有比synchronized更精确的线程语义和更好的性能.syncronized会自动释放锁,而Lock一定要程 ...