sqlsugar入门(4)-修改源码支持多主键保存ISaveable
1.查看其它接口发现少了一个最重要的SaveBuilder。此文件是存放sql模板,where条件,select解析,组装成tosqlstring的最后一个类。
添加文件
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Text.RegularExpressions; namespace SqlSugar
{
public class SaveBuilder : IDMLBuilder
{
public SaveBuilder()
{
this.sql = new StringBuilder();
this.DbColumnInfoList = new List<DbColumnInfo>();
this.SetValues = new List<KeyValuePair<string, string>>();
this.WhereValues = new List<string>();
this.Parameters = new List<SugarParameter>();
}
public SqlSugarProvider Context { get; set; }
public ILambdaExpressions LambdaExpressions { get; set; }
public ISqlBuilder Builder { get; set; }
public StringBuilder sql { get; set; }
public List<SugarParameter> Parameters { get; set; }
public string TableName { get; set; }
public string TableWithString { get; set; }
public List<DbColumnInfo> DbColumnInfoList { get; set; }
public List<string> WhereValues { get; set; }
public List<KeyValuePair<string, string>> SetValues { get; set; }
public bool IsNoUpdateNull { get; set; }
public bool IsNoUpdateDefaultValue { get; set; }
public List<string> PrimaryKeys { get; set; }
public bool IsOffIdentity { get; set; }
public bool IsWhereColumns { get; set; } /// <summary>
/// select x as X as a join T t on a.id = t.id
/// </summary> public virtual string SqlTemplate
{
get
{
return @"UPDATE {0} SET
{1} {2}"; }
} public virtual string SqlTemplateBatch
{
get
{
return @" SELECT {3} FROM (
{0} ) T ,{1} S WHERE {2}
; ";
}
} public virtual string SqlTemplateBatchSelect
{
get
{
return "{0} AS {1}";
}
} public virtual string SqlTemplateBatchUnion
{
get
{
return "\t\t\r\nUNION ALL ";
}
} public virtual void Clear()
{ }
public virtual string GetTableNameString
{
get
{
var result = Builder.GetTranslationTableName(TableName);
result += UtilConstants.Space;
if (this.TableWithString.HasValue())
{
result += TableWithString + UtilConstants.Space;
}
return result;
}
}
public virtual string GetTableNameStringNoWith
{
get
{
var result = Builder.GetTranslationTableName(TableName);
return result;
}
} public virtual ExpressionResult GetExpressionValue(Expression expression, ResolveExpressType resolveType, bool isMapping = true)
{
ILambdaExpressions resolveExpress = this.LambdaExpressions;
this.LambdaExpressions.Clear();
if (this.Context.CurrentConnectionConfig.MoreSettings != null)
{
resolveExpress.PgSqlIsAutoToLower = this.Context.CurrentConnectionConfig.MoreSettings.PgSqlIsAutoToLower;
}
else
{
resolveExpress.PgSqlIsAutoToLower = true;
}
if (isMapping)
{
resolveExpress.MappingColumns = Context.MappingColumns;
resolveExpress.MappingTables = Context.MappingTables;
resolveExpress.IgnoreComumnList = Context.IgnoreColumns;
resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices;
}
resolveExpress.InitMappingInfo = Context.InitMappingInfo;
resolveExpress.RefreshMapping = () =>
{
resolveExpress.MappingColumns = Context.MappingColumns;
resolveExpress.MappingTables = Context.MappingTables;
resolveExpress.IgnoreComumnList = Context.IgnoreColumns;
resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices;
};
resolveExpress.Resolve(expression, resolveType);
this.Parameters.AddRange(resolveExpress.Parameters);
var result = resolveExpress.Result;
return result;
}
public virtual string ToSqlString()
{
if (IsNoUpdateNull)
{
DbColumnInfoList = DbColumnInfoList.Where(it => it.Value != null).ToList();
}
if (IsNoUpdateDefaultValue)
{
DbColumnInfoList = DbColumnInfoList.Where(it => it.Value.ObjToString() !=UtilMethods.DefaultForType(it.PropertyType).ObjToString()).ToList();
}
var groupList = DbColumnInfoList.GroupBy(it => it.TableId).ToList(); return TomultipleSqlString(groupList);
} protected virtual string TomultipleSqlString(List<IGrouping<int, DbColumnInfo>> groupList)
{
Check.Exception(PrimaryKeys == null || PrimaryKeys.Count == 0, " Update List<T> need Primary key"); StringBuilder batchUpdateSql = new StringBuilder(); StringBuilder updateTable = new StringBuilder(); string selectString = string.Join(",", groupList.First().Select(
it =>
{
var result = "S." + it.DbColumnName + " " + Builder.GetTranslationColumnName(it.DbColumnName);
return result;
}
)); int i = 0;
foreach (var columns in groupList)
{
var isFirst = i == 0;
if (!isFirst)
{
updateTable.Append(SqlTemplateBatchUnion);
}
updateTable.Append("\r\n SELECT " + string.Join(",", columns.Where(o=>this.PrimaryKeys.Contains(o.DbColumnName)).Select(it => string.Format(SqlTemplateBatchSelect, FormatValue(it.Value), Builder.GetTranslationColumnName(it.DbColumnName)))));
++i;
}
updateTable.Append("\r\n");
string whereString = null;
//if (this.WhereValues.HasValue())
//{
// foreach (var item in WhereValues)
// {
// var isFirst = whereString == null;
// whereString += (isFirst ? null : " AND ");
// whereString += Regex.Replace(item, "\\" + this.Builder.SqlTranslationLeft, "S." + this.Builder.SqlTranslationLeft);
// }
//}
if (PrimaryKeys.HasValue())
{
foreach (var item in PrimaryKeys)
{
var isFirst = whereString == null;
whereString += (isFirst ? null : " AND ");
whereString += string.Format("S.{0}=T.{0}", Builder.GetTranslationColumnName(item));
}
}
batchUpdateSql.AppendFormat(SqlTemplateBatch, updateTable,this.TableName , whereString, selectString); return batchUpdateSql.ToString();
} public virtual object FormatValue(object value)
{
if (value == null)
{
return "NULL";
}
else
{
var type = UtilMethods.GetUnderType(value.GetType());
if (type == UtilConstants.DateType)
{
var date = value.ObjToDate();
if (date < Convert.ToDateTime("1900-1-1"))
{
date = Convert.ToDateTime("1900-1-1");
}
return "'" + date.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'";
}
else if (type == UtilConstants.ByteArrayType)
{
string bytesString = "0x" + BitConverter.ToString((byte[])value).Replace("-", "");
return bytesString;
}
else if (type.IsEnum())
{
return Convert.ToInt64(value);
}
else if (type == UtilConstants.BoolType)
{
return value.ObjToBool() ? "1" : "0";
}
else if (type == UtilConstants.StringType || type == UtilConstants.ObjType)
{
return "N'" + value.ToString().ToSqlFilter() + "'";
}
else
{
return "N'" + value.ToString() + "'";
}
}
}
}
}
2.修改SaveableProvider<T>使单主键查询数据库改为按条件解析查询existsObjects = this.Context.Ado.SqlQuery<T>(SaveBuilder.ToSqlString()).ToList();
3.添加动态表达式来筛选更新的数据以及插入的数据。
public List<T> insertObjects
{
get
{
var isDisableMasterSlaveSeparation = this.Context.Ado.IsDisableMasterSlaveSeparation;
this.Context.Ado.IsDisableMasterSlaveSeparation = true;
List<T> result = new List<T>();
var pks = GetPrimaryKeys();
Check.Exception(pks.IsNullOrEmpty(), "Need primary key"); var pkInfo = this.EntityInfo.Columns.Where(it => it.IsIgnore == false)
.Where(it => pks.Contains(it.DbColumnName)).ToList();
if (existsObjects == null)
{
SaveBuilder.PrimaryKeys = pks;
existsObjects = this.Context.Ado.SqlQuery<T>(SaveBuilder.ToSqlString()).ToList();
}
this.Context.Ado.IsDisableMasterSlaveSeparation = isDisableMasterSlaveSeparation;
ParameterExpression param1 = Expression.Parameter(typeof(T), "it");
ParameterExpression param = Expression.Parameter(typeof(T), "e");
BinaryExpression mainBinaryExpression = null;
foreach (var info in pkInfo)
{
MemberExpression body = Expression.PropertyOrField(param, info.PropertyName);
MemberExpression body1 = Expression.PropertyOrField(param1, info.PropertyName);
var exp = Expression.Equal(body, body1); if (mainBinaryExpression == null)
{
mainBinaryExpression = exp;
}
else
{
mainBinaryExpression = Expression.AndAlso(mainBinaryExpression, exp);
}
}
var lambda = Expression.Lambda<Func<T, Boolean>>(mainBinaryExpression, new[] { param });
Expression anyExpression = Expression.Call(
typeof(Enumerable), "Any",
new Type[] { typeof(T) },
Expression.Constant(existsObjects), lambda
);
var lambda1 = Expression.Lambda<Func<T, Boolean>>(Expression.Not(anyExpression), new[] { param1 });
return saveObjects.Where(lambda1.Compile()).ToList();
}
}
public List<T> updatObjects
{
get
{
var isDisableMasterSlaveSeparation = this.Context.Ado.IsDisableMasterSlaveSeparation;
this.Context.Ado.IsDisableMasterSlaveSeparation = true;
List<T> result = new List<T>();
var pks = GetPrimaryKeys();
Check.Exception(pks.IsNullOrEmpty(), "Need primary key"); var pkInfo = this.EntityInfo.Columns.Where(it => it.IsIgnore == false)
.Where(it => pks.Contains(it.DbColumnName)).ToList();
if (existsObjects == null)
{
SaveBuilder.PrimaryKeys = pks;
existsObjects = this.Context.Ado.SqlQuery<T>(SaveBuilder.ToSqlString()).ToList();
}
this.Context.Ado.IsDisableMasterSlaveSeparation = isDisableMasterSlaveSeparation;
ParameterExpression param1 = Expression.Parameter(typeof(T), "it");
ParameterExpression param = Expression.Parameter(typeof(T), "e");
BinaryExpression mainBinaryExpression = null;
foreach (var info in pkInfo)
{
MemberExpression body = Expression.PropertyOrField(param, info.PropertyName);
MemberExpression body1 = Expression.PropertyOrField(param1, info.PropertyName);
var exp = Expression.Equal(body, body1); if (mainBinaryExpression == null)
{
mainBinaryExpression = exp;
}
else
{
mainBinaryExpression = Expression.AndAlso(mainBinaryExpression, exp);
}
}
var lambda = Expression.Lambda<Func<T, Boolean>>(mainBinaryExpression, new[] { param });
Expression anyExpression = Expression.Call(
typeof(Enumerable), "Any",
new Type[] { typeof(T) },
Expression.Constant(existsObjects), lambda
);
var lambda1 = Expression.Lambda<Func<T, Boolean>>(anyExpression, new[] { param1 });
return saveObjects.Where(lambda1.Compile()).ToList();
}
}
4.添加tosql来打印生成的sql
ISaveable 添加tosql接口
List<KeyValuePair<string, List<SugarParameter>>> ToSql();
SaveableProvider实现接口
public List<KeyValuePair<string, List<SugarParameter>>> ToSql()
{
List<KeyValuePair<string, List<SugarParameter>>> sqllist = new List<KeyValuePair<string, List<SugarParameter>>>();
LoadInsertable();
LoadUpdateable();
if (insertable != null)
{
var insertsql = insertable.ToSql();
sqllist.Add(insertsql);
}
if (updateable != null)
{
var updatesql = updateable.ToSql();
sqllist.Add(updatesql);
} return sqllist;
}
Demo地址:https://gitee.com/xuanyun2018/sqlsugardemo.git
下一章节扩展分库分表功能。
sqlsugar入门(4)-修改源码支持多主键保存ISaveable的更多相关文章
- ok6410 u-boot-2012.04.01移植二修改源码支持单板
继ok6410 u-boot-2012.04.01移植一后修改代码,对ok6410单板初始化,主要包括时钟.串口.NAND.DDR等初始化.这些工作在以前的裸板程序都写了,直接拿来用.我觉得先写裸板程 ...
- 修改Cosbench源码 支持s3的 http range request 测试场景
在视频点播的业务应用场景中,用户使用了ffmpeg工具做视频实时转码用. 而ffmpeg使用range 请求.而Cosbench不支持这种测试场景,所以需要修改源码支持这种测试场景. HTTP 协议介 ...
- Windows7 64位环境6sv2.1大气传输模型修改源码添加国产高分卫星GF-1 GF-2光谱响应支持
下面开始添加国产卫星光谱响应的支持: 以下主要参考文章“6S大气传输模型修改源码添加.自定义卫星光谱响应(以HJ-1B CCD为例)”网址:http://blog.csdn.net/sam92/art ...
- 修改json源码支持datetime序列化
修改json源码支持datetime序列化 import json import datetime now = datetime.datetime.today() json.dumps(now) 抛出 ...
- Python paramiko 修改源码实现用户命令抓取
paramiko 源码修改 paramiko主要用来实现ssh客户端.服务端链接,上一节我们说到了堡垒机,堡垒机内有一个需求是“用户行为审计”,在这里我们就可以通过修改paramiko内文件的源码来实 ...
- Android5.1.1 - APK签名校验分析和修改源码绕过签名校验
Android5.1.1 - APK签名校验分析和修改源码绕过签名校验 作者:寻禹@阿里聚安全 APK签名校验分析 找到PackageParser类,该类在文件“frameworks/base/cor ...
- mvcAPI (入门 3)(源码)
mvcAPI (入门 3)(源码) http://download.csdn.net/detail/chunfang740/9078579
- element-ui 修改源码实践 --tranfer
1.element-ui 地址:https://github.com/ElemeFE/element 2.修改elelment-ui版本:2.2.2(请选择和项目相对应的版本) 3.修改内容:穿梭框组 ...
- zookeeper-如何修改源码-《每日五分钟搞定大数据》
本篇文章仅仅是起一个抛砖迎玉的作用,举一个如何修改源码的例子.文章的灵感来自 ZOOKEEPER-2784. 提一个问题先 之前的文章讲过zxid的设计,我们先复习下: zxid有64位,分成两部分: ...
随机推荐
- burp suite之spider(爬虫)
spider (蜘蛛,这里的意思指爬行) 像蜘蛛一样在网站上爬行出网站的个个目录信息,并发送至Target. 1.Control(控制) Spider is paused :停止蜘蛛爬行 Clear ...
- @Autowired,@Resource,@Qualifier,@Primary,@Inject的作用和区别
@Autowired注解的用法:可以用于构造器,方法,参数,字段进行属性注入,有一个required属性,默认是true,当改成false时,如果注入的属性在容器中不存在也不会报错@Resource该 ...
- RabbitMQ小记(一)
1.了解消息中间件 消息中间件,Message Queue Middleware,简称MQ,又称消息对列或消息对列中间件,利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式 ...
- 不知如何创建UML电路图?看看本文
Visual Paradigm是包含设计共享.线框图和数据库设计新特性的企业项目设计工具.现在你只需要这样单独的一款模型软件 Visual Paradigm就可以完成用UML设计软件,用BPMN去执行 ...
- python中np.arrange用法
转载:https://www.cnblogs.com/ghllfl/p/8487692.html np.arange()经常用,其用法总结如下: np.arange(0,60,2) 生成从0到60的步 ...
- DORIS系统概述
DORIS(Doppler Orbitography and Radio-positioning Integrated by Satellite)(多普勒轨道学与无线电定位集成卫星),它是由法国Cne ...
- NOIP提高组2016 D2T3 【愤怒的小鸟】
貌似还没有写过状压DP的题目,嗯,刚好今天考了,就拿出来写一写吧. 题目大意: 额,比较懒,这次就不写了... 思路分析: 先教大家一种判断题目是不是状压DP的方法吧. 很简单,那就是--看数据范围! ...
- 安装memcache,步骤
1.先下载emcache.rar安装包<ps:随便安装在哪里文件夹,或者新建文件夹都是可以的> 2.解压安装包<ps:运行里面的程序> 3.然后根据自己的phpstudy的版本 ...
- shell-的特殊变量-进程状态变量$$ $! $? $_详解
一:shell的特殊变量-进程状态变量详解 1. 进程状态变量 $$ 获取当前shell的进程号(pid) $! 执行上一个指令的pid,上一个后台运行进程的进程号 $? 获取执行上一个指令的返回值 ...
- 为什么在M3架构中 PC总是返回加4
由于CPU是3级流水线的方式运行.在执行第一条指令时候,已经对第二条指令译码,对第三条指令取值. PC总是指向正在取值的指令.由于在M3架构中,采用Thumb-2指令,每个指令占据2个字节,所以PC总 ...