使用LINQ生成Where的SQL语句
实例1-使用实例-单个语句:
int totalCount = ;
List<int> alist = new List<int> { , , };
List<User_info> userInfoList = UserCenterBus.Select_WebSiteBase<User_info>(, , User_info._USER_INFO_, User_info._ID_ + " DESC", out totalCount, m => alist.Contains(m.ID));
base.Response.Write(JsonHelper.ConvertJsonToStr(userInfoList));
/// <summary>
/// 自定义SQL分页查询_WebSite库_LINQ用于自定义分页SQL和非INT类型变量值传输(防止非INT类型值SQL注入)
/// </summary>
/// <typeparam name="T">返回类型</typeparam>
/// <param name="pageIndex">页码</param>
/// <param name="pageSize">页大小</param>
/// <param name="fromTableSql">select * from {0} where {1} order by {2}:填写{0}</param>
/// <param name="orderByTableFieldSql">select * from {0} where {1} order by {2}:填写{2}</param>
/// <param name="totalCount">总条数</param>
/// <param name="whereLinq">关于T的linq语句==>生成可DbParameter[]防SQL注入参数数组</param>
/// <returns></returns>
public static List<T> Select_WebSiteBase<T>(int pageIndex, int pageSize, string fromTableSql, string orderByTableFieldSql, out int totalCount, Expression<Func<T, bool>> whereLinq)
{
DB.MySql.WebSite.Entity.WherePart wherePart = DB.MySql.WebSite.Entity.WhereBuilder.Instance_MySql.ToSql<T>(whereLinq);
List<DbParameter> dbParameterList = new List<DbParameter>();
if (wherePart.Parameters != null && wherePart.Parameters.Count > )
{
foreach (var paramter in wherePart.Parameters)
{
dbParameterList.Add(new MySqlParameter(paramter.Key, paramter.Value));
}
}
string pageSql = string.Format(@"SELECT * FROM {0} WHERE {1} ORDER BY {2} LIMIT {3},{4};", fromTableSql, wherePart.Sql, orderByTableFieldSql, (pageIndex - ) * pageSize, pageSize);
string totalCountSql = string.Format(@"SELECT COUNT(*) FROM {0} WHERE {1};", fromTableSql, wherePart.Sql);
List<T> tList = DB.MySql.WebSite.BLL.BLLGeneric.Select<T>(CommandType.Text, pageSql + totalCountSql, out totalCount, dbParameterList.ToArray());
dbParameterList.Clear();
dbParameterList = null;
return tList;
}
实例2-使用实例-多个语句:
WhereBuilder whereBuilder = new WhereBuilder('`');
Expression<Func<Order_detail, bool>> expression = null;
expression = orderDetail => orderDetail.OrderDetailState == state;
WherePart columnValue = whereBuilder.ToSql<Order_detail>(expression);
expression = orderDetail => orderDetail.OrderID == orderId;
WherePart where = whereBuilder.ToSql<Order_detail>(expression); List<MySqlParameter> paramList = new List<MySqlParameter>(columnValue.Parameters.Count + where.Parameters.Count);
foreach (KeyValuePair<string, object> pair in columnValue.Parameters)
{
paramList.Add(new MySqlParameter("@" + pair.Key, pair.Value));
}
foreach (KeyValuePair<string, object> pair in where.Parameters)
{
paramList.Add(new MySqlParameter("@" + pair.Key, pair.Value));
} result = UpdateWhere(columnValue.Sql, where.Sql, paramList.ToArray()) == ;
Console.WriteLine(result);
使用LINQ生成Where的SQL语句:
参考资料:
http://ryanohs.com/2016/04/generating-sql-from-expression-trees-part-2/#more-394
http://stackoverflow.com/a/2616980/291955
主代码:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text; namespace ConsoleApplication2
{
/// <summary>
/// Generating SQL from expression trees, Part 2
/// http://ryanohs.com/2016/04/generating-sql-from-expression-trees-part-2/#more-394
/// </summary>
public class WhereBuilder
{
private readonly char _columnBeginChar = '[';
private readonly char _columnEndChar = ']';
private System.Collections.ObjectModel.ReadOnlyCollection<ParameterExpression> expressParameterNameCollection; public WhereBuilder(char columnChar = '`')
{
this._columnBeginChar = this._columnEndChar = columnChar;
} //public WhereBuilder(char columnBeginChar = '[', char columnEndChar = ']')
//{
// this._columnBeginChar = columnBeginChar;
// this._columnEndChar = columnEndChar;
//} /// <summary>
/// LINQ转SQL
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="expression"></param>
/// <returns></returns>
public WherePart ToSql<T>(Expression<Func<T, bool>> expression)
{
var i = ;
if (expression.Parameters.Count > )
{
this.expressParameterNameCollection = expression.Parameters;
}
return Recurse(ref i, expression.Body, isUnary: true);
} /// <summary>
/// LINQ转SQL
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="i">种子值</param>
/// <param name="expression"></param>
/// <returns></returns>
public WherePart ToSql<T>(ref int i, Expression<Func<T, bool>> expression)
{
if (expression.Parameters.Count > )
{
this.expressParameterNameCollection = expression.Parameters;
}
return Recurse(ref i, expression.Body, isUnary: true);
} /// <summary>
/// LINQ转SQL
/// </summary>
/// <param name="i">种子值</param>
/// <param name="expression"></param>
/// <param name="isUnary"></param>
/// <param name="prefix"></param>
/// <param name="postfix"></param>
/// <returns></returns>
private WherePart Recurse(ref int i, Expression expression, bool isUnary = false, string prefix = null, string postfix = null)
{
//运算符表达式
if (expression is UnaryExpression)
{
var unary = (UnaryExpression)expression;
//示例:m.birthday=DateTime.Now
if (unary.NodeType == ExpressionType.Convert)
{
var value = GetValue(expression);
if (value is string)
{
value = prefix + (string)value + postfix;
}
return WherePart.IsParameter(i++, value);
}
else
{
//示例:m.Birthday>'2018-10-31'
return WherePart.Concat(NodeTypeToString(unary.NodeType), Recurse(ref i, unary.Operand, true));
}
}
if (expression is BinaryExpression)
{
var body = (BinaryExpression)expression;
return WherePart.Concat(Recurse(ref i, body.Left), NodeTypeToString(body.NodeType), Recurse(ref i, body.Right));
}
//常量值表达式
//示例右侧表达式:m.ID=123;
if (expression is ConstantExpression)
{
var constant = (ConstantExpression)expression;
var value = constant.Value;
if (value is int)
{
return WherePart.IsSql(value.ToString());
}
if (value is string)
{
value = prefix + (string)value + postfix;
}
if (value is bool && isUnary)
{
return WherePart.Concat(WherePart.IsParameter(i++, value), "=", WherePart.IsSql(""));
}
return WherePart.IsParameter(i++, value);
}
//成员表达式
if (expression is MemberExpression)
{
var member = (MemberExpression)expression;
var memberExpress = member.Expression;
bool isContainsParameterExpress = false;
this.IsContainsParameterExpress(member, ref isContainsParameterExpress);
if (member.Member is PropertyInfo && isContainsParameterExpress)
{
var property = (PropertyInfo)member.Member;
//var colName = _tableDef.GetColumnNameFor(property.Name);
var colName = property.Name;
if (isUnary && member.Type == typeof(bool))
{
return WherePart.Concat(Recurse(ref i, expression), "=", WherePart.IsParameter(i++, true));
}
return WherePart.IsSql(string.Format("{0}{1}{2}", this._columnBeginChar, colName, this._columnEndChar));
}
if (member.Member is FieldInfo || !isContainsParameterExpress)
{
var value = GetValue(member);
if (value is string)
{
value = prefix + (string)value + postfix;
}
return WherePart.IsParameter(i++, value);
}
throw new Exception($"Expression does not refer to a property or field: {expression}");
}
//方法表达式
if (expression is MethodCallExpression)
{
var methodCall = (MethodCallExpression)expression;
//属性表达式中的参数表达式是否是表达式参数集合中的实例(或者表达式中包含的其他表达式中的参数表达式)
bool isContainsParameterExpress = false;
this.IsContainsParameterExpress(methodCall, ref isContainsParameterExpress);
if (isContainsParameterExpress)
{
// LIKE queries:
if (methodCall.Method == typeof(string).GetMethod("Contains", new[] { typeof(string) }))
{
return WherePart.Concat(Recurse(ref i, methodCall.Object), "LIKE", Recurse(ref i, methodCall.Arguments[], prefix: "%", postfix: "%"));
}
if (methodCall.Method == typeof(string).GetMethod("StartsWith", new[] { typeof(string) }))
{
return WherePart.Concat(Recurse(ref i, methodCall.Object), "LIKE", Recurse(ref i, methodCall.Arguments[], postfix: "%"));
}
if (methodCall.Method == typeof(string).GetMethod("EndsWith", new[] { typeof(string) }))
{
return WherePart.Concat(Recurse(ref i, methodCall.Object), "LIKE", Recurse(ref i, methodCall.Arguments[], prefix: "%"));
}
// IN queries:
if (methodCall.Method.Name == "Contains")
{
Expression collection;
Expression property;
if (methodCall.Method.IsDefined(typeof(ExtensionAttribute)) && methodCall.Arguments.Count == )
{
collection = methodCall.Arguments[];
property = methodCall.Arguments[];
}
else if (!methodCall.Method.IsDefined(typeof(ExtensionAttribute)) && methodCall.Arguments.Count == )
{
collection = methodCall.Object;
property = methodCall.Arguments[];
}
else
{
throw new Exception("Unsupported method call: " + methodCall.Method.Name);
}
var values = (IEnumerable)GetValue(collection);
return WherePart.Concat(Recurse(ref i, property), "IN", WherePart.IsCollection(ref i, values));
}
}
else
{
var value = GetValue(expression);
if (value is string)
{
value = prefix + (string)value + postfix;
}
return WherePart.IsParameter(i++, value);
} throw new Exception("Unsupported method call: " + methodCall.Method.Name);
}
//New表达式
if (expression is NewExpression)
{
var member = (NewExpression)expression;
var value = GetValue(member);
if (value is string)
{
value = prefix + (string)value + postfix;
}
return WherePart.IsParameter(i++, value);
}
throw new Exception("Unsupported expression: " + expression.GetType().Name);
}
/// <summary>
/// 判断表达式内部是否含有变量M
/// </summary>
/// <param name="expression">表达式</param>
/// <returns></returns>
private void IsContainsParameterExpress(Expression expression, ref bool result)
{
if (this.expressParameterNameCollection != null && this.expressParameterNameCollection.Count > && expression != null)
{
if (expression is MemberExpression)
{
if (this.expressParameterNameCollection.Contains(((MemberExpression)expression).Expression))
{
result = true;
}
}
else if (expression is MethodCallExpression)
{
MethodCallExpression methodCallExpression = (MethodCallExpression)expression; if (methodCallExpression.Object != null)
{
if (methodCallExpression.Object is MethodCallExpression)
{
//判断示例1:m.ID.ToString().Contains("123")
this.IsContainsParameterExpress(methodCallExpression.Object, ref result);
}
else if (methodCallExpression.Object is MemberExpression)
{
//判断示例2:m.ID.Contains(123)
MemberExpression MemberExpression = (MemberExpression)methodCallExpression.Object;
if (MemberExpression.Expression != null && this.expressParameterNameCollection.Contains(MemberExpression.Expression))
{
result = true;
}
}
}
//判断示例3: int[] ids=new ids[]{1,2,3}; ids.Contains(m.ID)
if (result == false && methodCallExpression.Arguments != null && methodCallExpression.Arguments.Count > )
{
foreach (Expression express in methodCallExpression.Arguments)
{
if (express is MemberExpression || express is MethodCallExpression)
{
this.IsContainsParameterExpress(express, ref result);
}
else if (this.expressParameterNameCollection.Contains(express))
{
result = true;
break;
}
}
}
}
}
} private static object GetValue(Expression member)
{
// source: http://stackoverflow.com/a/2616980/291955
var objectMember = Expression.Convert(member, typeof(object));
var getterLambda = Expression.Lambda<Func<object>>(objectMember);
var getter = getterLambda.Compile();
return getter();
} private static string NodeTypeToString(ExpressionType nodeType)
{
switch (nodeType)
{
case ExpressionType.Add:
return "+";
case ExpressionType.And:
return "&";
case ExpressionType.AndAlso:
return "AND";
case ExpressionType.Divide:
return "/";
case ExpressionType.Equal:
return "=";
case ExpressionType.ExclusiveOr:
return "^";
case ExpressionType.GreaterThan:
return ">";
case ExpressionType.GreaterThanOrEqual:
return ">=";
case ExpressionType.LessThan:
return "<";
case ExpressionType.LessThanOrEqual:
return "<=";
case ExpressionType.Modulo:
return "%";
case ExpressionType.Multiply:
return "*";
case ExpressionType.Negate:
return "-";
case ExpressionType.Not:
return "NOT";
case ExpressionType.NotEqual:
return "<>";
case ExpressionType.Or:
return "|";
case ExpressionType.OrElse:
return "OR";
case ExpressionType.Subtract:
return "-";
}
throw new Exception($"Unsupported node type: {nodeType}");
}
} public class WherePart
{
/// <summary>
/// 含有参数变量的SQL语句
/// </summary>
public string Sql { get; set; }
/// <summary>
/// SQL语句中的参数变量
/// </summary>
public Dictionary<string, object> Parameters { get; set; } = new Dictionary<string, object>(); public static WherePart IsSql(string sql)
{
return new WherePart()
{
Parameters = new Dictionary<string, object>(),
Sql = sql
};
} public static WherePart IsParameter(int count, object value)
{
return new WherePart()
{
Parameters = { { count.ToString(), value } },
Sql = $"@{count}"
};
} public static WherePart IsCollection(ref int countStart, IEnumerable values)
{
var parameters = new Dictionary<string, object>();
var sql = new StringBuilder("(");
foreach (var value in values)
{
parameters.Add((countStart).ToString(), value);
sql.Append($"@{countStart},");
countStart++;
}
if (sql.Length == )
{
sql.Append("null,");
}
sql[sql.Length - ] = ')';
return new WherePart()
{
Parameters = parameters,
Sql = sql.ToString()
};
} public static WherePart Concat(string @operator, WherePart operand)
{
return new WherePart()
{
Parameters = operand.Parameters,
Sql = $"({@operator} {operand.Sql})"
};
} public static WherePart Concat(WherePart left, string @operator, WherePart right)
{
return new WherePart()
{
Parameters = left.Parameters.Union(right.Parameters).ToDictionary(kvp => kvp.Key, kvp => kvp.Value),
Sql = $"({left.Sql} {@operator} {right.Sql})"
};
}
}
}
使用LINQ生成Where的SQL语句的更多相关文章
- IT咨询顾问:一次吐血的项目救火 java或判断优化小技巧 asp.net core Session的测试使用心得 【.NET架构】BIM软件架构02:Web管控平台后台架构 NetCore入门篇:(十一)NetCore项目读取配置文件appsettings.json 使用LINQ生成Where的SQL语句 js_jquery_创建cookie有效期问题_时区问题
IT咨询顾问:一次吐血的项目救火 年后的一个合作公司上线了一个子业务系统,对接公司内部的单点系统.我收到该公司的技术咨询:项目启动后没有规律的突然无法登录了,重新启动后,登录一断时间后又无法重新登 ...
- LinqToDB 源码分析——生成与执行SQL语句
生成SQL语句的功能可以算是LinqToDB框架的最后一步.从上一章中我们可以知道处理完表达式树之后,相关生成SQL信息会被保存在一个叫SelectQuery类的实例.有了这个实例我们就可以生成对应的 ...
- C#——反射,自动生成添加的SQL语句
C#中的反射.是C#中特别重要也是特别神奇的特性,对后面学习框架,了解框架的原理.以及自己写框架,都是必不可少的.学习反射的过程中.总给我一种茅塞顿开的感觉,以前不懂的,现在懂了 反射的介绍:http ...
- php如何妩媚地生成执行的sql语句
会不会碰到这样一种情况呢?每次获取数据将数据和历史版本都有一定的差别,然而用ThinkPHP的addAll()函数,却会将已有的数据删掉再重新写入.这明显不是我们想要的.但自己写sql每次几十个字段也 ...
- 根据Model有值的自动生成添加的Sql语句
static string Table_Name = ""; /// <summary> /// model实体中的字段名相对数据库表添加的字段 /// 如: /// ...
- 通过实体类生成建表SQL语句实现方法
import java.io.File; import java.io.FileOutputStream; import java.lang.reflect.Field; import java.ut ...
- sql server 生成数据库字典 sql语句
SELECT TOP 100 PERCENT --a.id, CASE WHEN a.colorder = 1 THEN d.name ELSE '' END AS 表名, ...
- Mysql生成UUID的SQL语句
大写的UUID: SELECT UPPER(UUID()); 小写的UUID: SELECT LOWER(UUID()); SELECT UUID(); 去掉横杠的UUID: SELECT REPLA ...
- 深入理解 LINQ to SQL 生成的 SQL 语句
Ø 简介 在 C# 中与数据交互最常用的语句就是 LINQ 了,而 LINQ to SQL 是最直接与数据库打交道的语句,它可以根据 LINQ 语法生成对应的 SQL 语句,在数据库中去执行.本文主 ...
随机推荐
- 1042.D Petya and Array 前缀 + 树状数组
11.19.2018 1042.D Petya and ArrayNew Point: 前缀 + 树状数组 :树状数组逐个维护前缀个数 Describe: 给你一个数组,一个标记数,问你有多少区间[l ...
- access纯jdbc连接
Class.forName("com.hxtt.sql.access.AccessDriver"); String url = "jdbc:Access:///c:/a/ ...
- visual studio 2015 Opencv 3.4.0配置
因为想做AR方面,需要了解计算机视觉知识,决定从opencv开始入门,在网上买了本毛星云的<Opencv3编程入门>开始自学. 一.opencv 3.4.0下载安装 在官网http://o ...
- CentOS6.2上安装pip
如果yum install pip执行失败.按如下步骤执行 首先安装epel扩展源: yum -y install epel-release 然后执行yum --disablerepo=epel -y ...
- Delphi XE2 新增 System.Zip 单元, 可用一句话压缩整个文件夹了
内主要就是 TZipFile 类, 最方便使用的是它的类方法: TZipFile.ExtractZipFile() //解压 Zip 文件到指定文件夹 TZipFile.IsValid() //判断指 ...
- 细说MySQL数据库操作
目录 基本语法: 字符集和校验规则 字符集 校验规则 校验规则的影响 数据库操作相关指令 查询数据库版本 显示数据库语句 显示数据库创建语句 数据库删除语句 查看当前数据库有多少个用户在操作 基本语法 ...
- C++ Opencv Mat类型使用的几个注意事项及自写函数实现Laplace图像锐化
为了提升自己对Opencv中Mat数据类型的熟悉和掌握程度,自己尝试着写了一下Laplace图像锐化函数,一路坎坷,踩坑不断.现将代码分享如下: #include <opencv2/opencv ...
- Hadoop面试题
1.把数据仓库从传统关系数据库转到hadoop有什么优势? 原关系存储方式昂贵 空间有限 hadoop支持结构化(例如 RDBMS),非结构化(例如 images,PDF,docs )和半结构化(例如 ...
- css3新特性总结
一.什么是css3 css用于控制网页的样式和布局,css3是css的升级版本,受浏览器限制,跨浏览器开发有点复杂.css3完全向后兼容 二.css3新特性 1.边框 css3的边框有如下属性: (1 ...
- JavaScript优化细节(一)
1.置空Closure(闭包)引起的Memory leak滞留的Object和domain 2.用fragment实现append大量元素 var f= document.createDocument ...